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.

ngModel + ngList binding to array does not update view when model changes #1751

Open

Description

@danilsomsikov

See: http://jsfiddle.net/fjQcu/4/

The reason for that is object reference comparison at input.js:1050

Activity

  1. added 2 commits that reference this issue on Apr 30, 2013
    26207db
    f2af60c
  2. btford commented on Aug 24, 2013

    @btford
    Contributor

    As part of our effort to clean out old issues, this issue is being automatically closed since it has been inactivite for over two months.

    Please try the newest versions of Angular (1.0.8 and 1.2.0-rc.1), and if the issue persists, comment below so we can discuss it.

    Thanks!

  3. danilsomsikov commented on Aug 26, 2013

    @danilsomsikov
    ContributorAuthor

    The issue hasn't been fixed in either version.
    See http://jsfiddle.net/fjQcu/8/ for 1.2.0-rc.1 and http://jsfiddle.net/fjQcu/9/ for 1.0.8

  4. reopened this on Aug 26, 2013
  5. lordfriend commented on Nov 1, 2014

    @lordfriend

    I also encounter this issue when using ng-model in my custom directive. It seems ngModelController using reference comparison leads the $render callback never being called when array is just an old reference but its content changes. angular v1.2.23

  6. jamie-pate commented on Dec 10, 2014

    @jamie-pate

    Workaround:

    make a new directive, something like:

    function ngeModelCollection() {
        return {
            require: 'ngModel',
            link: function(scope, elem, attr, ctrl) {
                $scope.$watchCollection(attr.ngModel, function ngModelWatch(value, old) {
                if (!Array.isArray(value) || old !== value) {
                    return;
                }
        ///copypasta from ngModelWatch()
          var formatters = ctrl.$formatters,
              idx = formatters.length;
    
          ctrl.$modelValue = value;
          while(idx--) {
            value = formatters[idx](value);
          }
    
          if (ctrl.$viewValue !== value) {
            ctrl.$viewValue = value;
            ctrl.$render();
          }
        ////endcopypasta
    
            }//end link function
        }
    }
    
    

    (untested, may need tweaking)

  7. kapace commented on Dec 11, 2014

    @kapace
    Contributor

    👍 Just formatting Jamie's workaround

    function ngeModelCollection() {
        return {
            require: 'ngModel',
            link: function(scope, elem, attr, ctrl) {
                $scope.$watchCollection(attr.ngModel, function ngModelWatch(value, old) {
                    if (!Array.isArray(value) || old === value) {
                        return;
                    }
    
                    ///copypasta from ngModelWatch()
                    var formatters = ctrl.$formatters,
                        idx = formatters.length;
    
                    ctrl.$modelValue = value;
                    while (idx--) {
                        value = formatters[idx](value);
                    }
    
                    if (ctrl.$viewValue !== value) {
                        ctrl.$viewValue = value;
                        ctrl.$render();
                    }
                });
                ////endcopypasta
            }//end link function
        };
    }
  8. Hotell commented on Feb 8, 2015

    @Hotell
    Contributor

    I've created this workaround via new directive.
    It's more performant than @jamie-pate solution , 'cause the $viewValue update is processed only on external $modelValue changes and only one $formatter ngList formatter is run and $modelValue is not reassigned(there is no reason to do that) inside listener function.

      angular.module('myApp')
        .directive('emNgList', emNgList)
        ;
    
        function emNgList(){
    
          return {
            restrict: 'A',
            require: 'ngModel',
            priority: 100, // this has to be eq or gt as ngList.priority to get ngList $formatter
            link: postLink
          };
    
          function postLink(scope, elem, attrs, ctrl){
    
              var ngListFormatter = getNgListFormatter(ctrl);
    
              var killMe = scope.$watchCollection(attrs.ngModel, function(modelValue){
    
                var newViewValue = ngListFormatter(modelValue);
    
                if(newViewValue !== ctrl.$viewValue){
    
                  ctrl.$viewValue = newViewValue;
                  ctrl.$render();
    
                }
    
              });
    
            scope.$on('$destroy',function(){ killMe(); });
    
          }
    
          function getNgListFormatter(ngModelCtrl){
    
            var formatters = ngModelCtrl.$formatters;
            var lastIdx = formatters.length - 1;
    
            return formatters[lastIdx];
          }
        }

    showcase:
    http://plnkr.co/edit/3ExCYEhmhAp1pL21ll3X?p=preview

  9. self-assigned this
    on Sep 14, 2015
  10. modified the milestones: , on Sep 14, 2015
  11. modified the milestones: 1.5.x, on Apr 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions