Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

select multi: $render is called twice when model reference changes #12731

Open
@tomyam1

Description

@tomyam1

This is a followup on a previous issue. I've just found this issue on my own directives and I think it'd be better fixed in angular as well.

The $render function of a multi-select element is called twice whenever the model value changes by reference.
See plnker: http://plnkr.co/edit/1npwJi5tCS7gGLafYfRp?p=preview

After a model changes, $render is called first from ngModel.
It will be be called again from the viewValue watch of the select directive.

This can be fixed by keeping the last rendered value instead of the last view value in select:

// https://github.com/angular/angular.js/blob/master/src/ng/directive/select.js#L368

var lastRendered;

ngModelCtrl.$render = function() {
  selectCtrl.writeValue(ngModelCtrl.$viewValue);
  if (attr.multiple) {
    lastRendered = shallowCopy(ngModelCtrl.$viewValue);
  }
};

...

if (attr.multiple) {

  ...
  // we have to do it on each watch since ngModel watches reference, but
  // we need to work of an array, so we need to see if anything was inserted/removed
  var lastViewRef = NaN;
  scope.$watch(function selectMultipleWatch() {
    if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastRendered, ngModelCtrl.$viewValue)) {
      ngModelCtrl.$render();
    }
    lastViewRef = ngModelCtrl.$viewValue;
  });

}

To make the spec cover this case. Just add an additional $digest after every $apply (before checking the number of $render calls).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions