Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two way binding Angularjs directives isn't working

I have been trying to figure out the solution but I think i hit a dead end.

So here is my directive

directives.directive('postprocess', function($compile)
{
    return {
        restrict : 'E',
        require: '^ngModel',
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs) {
            var parsed = scope.ngModel;
            el = $compile(parsed)(scope);
            element.html("");
            //add some other html entities/styles.
            element.append(el);
            console.log(parsed);
        }  
    };
});

The html

<postprocess ng-model="some_model.its_property" style="padding-top: 10px;" />

Somewhere in the controller, I update the model property

some_model.its_property = 'Holla';

But it doesn't update the corresponding directive. It works perfectly when loading which tells me that it might not be entirely a scoping issue.

like image 990
Saikiran Yerram Avatar asked Oct 01 '13 16:10

Saikiran Yerram


People also ask

Does AngularJS support two way binding?

AngularJS creates a two way data-binding between the select element and the $ctrl.

Which object is used for two way data-binding in AngularJS?

Two-way data binding is achieved by using the ng-model directive.

What is two way binding in AngularJS?

Two-way Binding Data binding in AngularJS is the synchronization between the model and the view. When data in the model changes, the view reflects the change, and when data in the view changes, the model is updated as well.

What does $compile do in AngularJS?

Overview. Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together. The compilation is a process of walking the DOM tree and matching DOM elements to directives. Note: This document is an in-depth reference of all directive options.


1 Answers

It's much simpler, so I have removed some extra code you had there.

Please take a look at the code below or working Plunker:

<!doctype html>
<html lang="en" ng-app="myApp">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>

    <script>
        var myApp = angular.module('myApp', []);
        myApp.directive('postprocess', function ($timeout) {
            return {
                restrict : 'E',
                transclude: 'true',
                scope: {
                    myVariable: '='
                },
                link: function(scope, element, attrs) {
                    $timeout(function () {
                        scope.myVariable = 'Bye bye!'
                    }, 200);
                }  
            };
        });

        myApp.controller('myAppCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
            $scope.myVariable = {
                value : 'Holla'
            };

            console.log($scope.myVariable.value); // -> prints initial value
            $timeout(function () {
                console.log($scope.myVariable.value); // -> prints value after it is changed by the directive
            }, 2000);
        }])
    </script>

    </head>
    <body ng-controller="myAppCtrl">
        <postprocess my-variable="myVariable.value" style="padding-top: 10px;" />
    </body>
</html>
  1. The controller sets the initial value to 'Holla'
  2. The directive receives that value by the my-variable attribute
  3. Using two way data-binding any changes made to scope.myVariable updates the $scope.myVariable of the main controller
  4. After few seconds $scope.myVariable changes to 'Bye Bye'
  5. Take a look at your console.log

$watch and $apply

Angular's two-way data binding is the root of all awesome in Angular. However, it's not magic, and there are some situations where you need to give it a nudge in the right direction.

When you bind a value to an element in Angular using ng-model, ng-repeat, etc., Angular creates a $watch on that value. Then whenever a value on a scope changes, all $watches observing that element are executed, and everything updates.

Sometimes, usually when you're writing a custom directive, you will have to define your own $watch on a scope value to make the directive react to changes.

On the flip side, sometimes you change a scope value in some code but the app doesn't react to it. Angular checks for scope variable changes after pieces of your code have finished running; for example, when ng-click calls a function on your scope, Angular will check for changes and react. However, some code is outside of Angular and you'll have to call scope.$apply() yourself to trigger the update. This is most commonly seen in event handlers in custom directives.

like image 142
Denison Luz Avatar answered Oct 15 '22 17:10

Denison Luz