Arkadiusz Kałkus
Arkadiusz Kałkus

Reputation: 18433

An input inside a component breaks two-way binding of AngularJS

I created a simple component:

(function (module) {
    'use strict';
    function SomeCtrl() {
        this.foo = function (event) {
            this.someArray.forEach(function (part, index, array) {
                //somelogic
                array[index] = array[index] + " (foo)";
            });            
        }
    }

    module.component('componentName', {
        templateUrl: 'blah.html',
        controller: SomeCtrl,
        bindings: {
            someArray: '=',
        }
    });
})(module);

Html template is also simple:

<div class="input-group">
    <input type="text" class="form-control" ng-model="$ctrl.someArray" />
    <span class="input-group-btn">
        <a class="btn btn-default" ng-click="$ctrl.foo($event)">
            <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </span>
</div>
{{$ctrl.someArray}}

Basically it's some input, and button. Input is bound with array, and on button click array is modified.

Unfortunately component behaves strange. Expression ({{$ctrl.someArray}}) is updated, but input value stays the same.

On the other hand, when user modify input value, then expression changes properly.

There are no errors thrown, no nothing. It's not even one-way binding, but unusual block of data flow...

Upvotes: 0

Views: 221

Answers (2)

Arkadiusz Kałkus
Arkadiusz Kałkus

Reputation: 18433

The problem lies in how the array is updated:

this.someArray.forEach(function (part, index, array) {
    //somelogic
    array[index] = array[index] + " (foo)";
}); 

It seems that AngularJS doesn't detect this kind of changes performed on the array. Solution is quite simple:

var newArray = []
this.someArray.forEach(function (part, index, array) {
    //somelogic
    newArray.push(array[index] + " (foo)");
}); 
this.someArray = newArray;

Upvotes: 0

Manikandan Velayutham
Manikandan Velayutham

Reputation: 2228

var module = angular.module('myApp',[]);
    module.component('componentName', {
    controller: function SomeCtrl() { 
        this.foo = function (event, array) { 
 this.someArray.forEach(function (part, index, array) {
                //somelogic
              //  array[index] ={'no':array[index].no+ " foo"};
                 console.log(array[index] ={'no':array[index].no+ " foo"});
            });  
          
        }
    }, 
        template: `<div class="input-group">
    <input type="text" ng-repeat="some in $ctrl.someArray" class="form-control" ng-model="some.no" /><br>{{$ctrl.someArray}}
   
        <button class="btn btn-default" ng-click="$ctrl.foo($event, $ctrl.someArray)">
        Okay
        </button>
 
</div>`,         
        bindings: {
            someArray: '=',
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>
<body ng-app="myApp">
<div ng-init="arrays=[{'no':'1'},{'no':'2'},{'no':'3'},{'no':'4'},{'no':'5'}]">
<component-name some-array="arrays"></component-name>
</div>
</body>

Upvotes: 0

Related Questions