diff options
Diffstat (limited to 'src/widget/select.js')
| -rw-r--r-- | src/widget/select.js | 138 | 
1 files changed, 67 insertions, 71 deletions
| diff --git a/src/widget/select.js b/src/widget/select.js index f70575a6..e7386147 100644 --- a/src/widget/select.js +++ b/src/widget/select.js @@ -123,87 +123,79 @@   */  var ngOptionsDirective = valueFn({ terminal: true }); -var selectDirective = ['$formFactory', '$compile', '$parse', -               function($formFactory,   $compile,   $parse){ +var selectDirective = ['$compile', '$parse', function($compile,   $parse) {                           //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777    var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/;    return {      restrict: 'E', -    link: function(modelScope, selectElement, attr) { -      if (!attr.ngModel) return; -      var form = $formFactory.forElement(selectElement), -          multiple = attr.multiple, -          optionsExp = attr.ngOptions, -          modelExp = attr.ngModel, -          widget = form.$createWidget({ -            scope: modelScope, -            model: modelExp, -            onChange: attr.ngChange, -            alias: attr.name, -            controller: ['$scope', optionsExp ? Options : (multiple ? Multiple : Single)]}); - -      selectElement.bind('$destroy', function() { widget.$destroy(); }); - -      widget.$pristine = !(widget.$dirty = false); - -      widget.$on('$validate', function() { -        var valid = !attr.required || !!widget.$modelValue; -        if (valid && multiple && attr.required) valid = !!widget.$modelValue.length; -        if (valid !== !widget.$error.REQUIRED) { -          widget.$emit(valid ? '$valid' : '$invalid', 'REQUIRED'); -        } -      }); +    require: '?ngModel', +    link: function(scope, element, attr, ctrl) { +      if (!ctrl) return; + +      var multiple = attr.multiple, +          optionsExp = attr.ngOptions; + +      // required validator +      if (multiple && (attr.required || attr.ngRequired)) { +        var requiredValidator = function(value) { +          ctrl.emitValidity('REQUIRED', !attr.required || (value && value.length)); +          return value; +        }; -      widget.$on('$viewChange', function() { -        widget.$pristine = !(widget.$dirty = true); -      }); +        ctrl.parsers.push(requiredValidator); +        ctrl.formatters.unshift(requiredValidator); -      forEach(['valid', 'invalid', 'pristine', 'dirty'], function(name) { -        widget.$watch('$' + name, function(value) { -          selectElement[value ? 'addClass' : 'removeClass']('ng-' + name); +        attr.$observe('required', function() { +          requiredValidator(ctrl.viewValue);          }); -      }); +      } + +      if (optionsExp) Options(scope, element, ctrl); +      else if (multiple) Multiple(scope, element, ctrl); +      else Single(scope, element, ctrl); +        //////////////////////////// -      function Multiple(widget) { -        widget.$render = function() { -          var items = new HashMap(this.$viewValue); -          forEach(selectElement.children(), function(option){ -            option.selected = isDefined(items.get(option.value)); -          }); + + +      function Single(scope, selectElement, ctrl) { +        ctrl.render = function() { +          selectElement.val(ctrl.viewValue);          };          selectElement.bind('change', function() { -          widget.$apply(function() { -            var array = []; -            forEach(selectElement.children(), function(option){ -              if (option.selected) { -                array.push(option.value); -              } -            }); -            widget.$emit('$viewChange', array); +          scope.$apply(function() { +            ctrl.touch(); +            ctrl.read(selectElement.val());            });          }); -        } -      function Single(widget) { -        widget.$render = function() { -          selectElement.val(widget.$viewValue); +      function Multiple(scope, selectElement, ctrl) { +        ctrl.render = function() { +          var items = new HashMap(ctrl.viewValue); +          forEach(selectElement.children(), function(option) { +            option.selected = isDefined(items.get(option.value)); +          });          };          selectElement.bind('change', function() { -          widget.$apply(function() { -            widget.$emit('$viewChange', selectElement.val()); +          scope.$apply(function() { +            var array = []; +            forEach(selectElement.children(), function(option) { +              if (option.selected) { +                array.push(option.value); +              } +            }); +            ctrl.touch(); +            ctrl.read(array);            });          }); - -        widget.$viewValue = selectElement.val();        } -      function Options(widget) { +      function Options(scope, selectElement, ctrl) {          var match;          if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) { @@ -234,15 +226,15 @@ var selectDirective = ['$formFactory', '$compile', '$parse',              // developer declared null option, so user should be able to select it              nullOption = jqLite(option).remove();              // compile the element since there might be bindings in it -            $compile(nullOption)(modelScope); +            $compile(nullOption)(scope);            }          });          selectElement.html(''); // clear contents          selectElement.bind('change', function() { -          widget.$apply(function() { +          scope.$apply(function() {              var optionGroup, -                collection = valuesFn(modelScope) || [], +                collection = valuesFn(scope) || [],                  locals = {},                  key, value, optionElement, index, groupIndex, length, groupLength; @@ -259,7 +251,7 @@ var selectDirective = ['$formFactory', '$compile', '$parse',                      key = optionElement.val();                      if (keyName) locals[keyName] = key;                      locals[valueName] = collection[key]; -                    value.push(valueFn(modelScope, locals)); +                    value.push(valueFn(scope, locals));                    }                  }                } @@ -272,17 +264,21 @@ var selectDirective = ['$formFactory', '$compile', '$parse',                } else {                  locals[valueName] = collection[key];                  if (keyName) locals[keyName] = key; -                value = valueFn(modelScope, locals); +                value = valueFn(scope, locals);                }              } -            if (isDefined(value) && modelScope.$viewVal !== value) { -              widget.$emit('$viewChange', value); +            ctrl.touch(); + +            if (ctrl.viewValue !== value) { +              ctrl.read(value);              }            });          }); -        widget.$watch(render); -        widget.$render = render; +        ctrl.render = render; + +        // TODO(vojta): can't we optimize this ? +        scope.$watch(render);          function render() {            var optionGroups = {'':[]}, // Temporary location for the option groups before we render them @@ -291,8 +287,8 @@ var selectDirective = ['$formFactory', '$compile', '$parse',                optionGroup,                option,                existingParent, existingOptions, existingOption, -              modelValue = widget.$modelValue, -              values = valuesFn(modelScope) || [], +              modelValue = ctrl.modelValue, +              values = valuesFn(scope) || [],                keys = keyName ? sortedKeys(values) : values,                groupLength, length,                groupIndex, index, @@ -313,20 +309,20 @@ var selectDirective = ['$formFactory', '$compile', '$parse',            // We now build up the list of options we need (we merge later)            for (index = 0; length = keys.length, index < length; index++) {                 locals[valueName] = values[keyName ? locals[keyName]=keys[index]:index]; -               optionGroupName = groupByFn(modelScope, locals) || ''; +               optionGroupName = groupByFn(scope, locals) || '';              if (!(optionGroup = optionGroups[optionGroupName])) {                optionGroup = optionGroups[optionGroupName] = [];                optionGroupNames.push(optionGroupName);              }              if (multiple) { -              selected = selectedSet.remove(valueFn(modelScope, locals)) != undefined; +              selected = selectedSet.remove(valueFn(scope, locals)) != undefined;              } else { -              selected = modelValue === valueFn(modelScope, locals); +              selected = modelValue === valueFn(scope, locals);                selectedSet = selectedSet || selected; // see if at least one item is selected              }              optionGroup.push({                id: keyName ? keys[index] : index,   // either the index into array or key from object -              label: displayFn(modelScope, locals) || '', // what will be seen by the user +              label: displayFn(scope, locals) || '', // what will be seen by the user                selected: selected                   // determine if we should be selected              });            } | 
