Mad-D
Mad-D

Reputation: 4669

Data share between directive and controller in AngularJS

I need to take a step back and understand the data flow between controllers to directive, directive to controller and the inline template vs template url in directives.

I have customDirective created with both inline template as well templateUrl for testing purpose. I have attached few values to scope in controller ( obj.prop= "Germany", name.firstname= "Gotze", originalBill="$20" ) and will change the values in directive and add one more ( obj.prop= "USA", name.firstname= "Tom", originalBill= not changed, bill="4000", applyTest="New Value" ). So i expect inline or url template to display values from directive and retain the unchanged values from the controller.

index

<pass-object obj="obj" name="name" bill="bill" originalBill="originalBill" applyTest="applyTest"></pass-object>

customDirective

app.directive('passObject', function() {
return {
    restrict: 'AE',
    scope: { 
      obj: '=',
      name:'=',
      bill:'=',
      applyTest:'='
    },
   templateUrl:'./customDirective.html',
  /* template: `<div style="color:brown">
              =====Directive Inline Template===== <br/>
              Country Name : {{obj.prop}}! <br/>
              Person Name: {{name.firstname}} <br/>
              Original money : {{originalBill}} <br/>
              Bill Money: {{bill}} <br/>
              Testing Apply: {{applyTest}} <br/>
              Two Way Binding: <input type="text" ng-model="obj.prop" ng-model="name.firstname"/>
              </div>`,
    */
    link: function(scope, element, attrs){
      scope.name = { firstname: "Tom" };
      scope.obj = { prop: "USA" };
      scope.bill="$4000";

      scope.$apply(function() {
        scope.applyTest= " New Value";
      });
    }
};
});

Problem/Confusion ( check plunker ):
1. when you use templateUrl, why didn't obj.prop, name.firstname change from directive but the values in index page changed from directive ?
2. when you use inline template both in index and inline html reflects right values from directive for obj.prop, name.firstname; but originalBill doesn't get the value ?
3. Why can't i retrieve applyTest value from scope?

Plunker

Upvotes: 0

Views: 508

Answers (2)

Vindhyachal Kumar
Vindhyachal Kumar

Reputation: 1794

  1. when you use templateUrl, why didn't obj.prop, name.firstname change from directive but the values in index page changed from directive ?

    Answer: because you have used controller 'MainCtrl' in html file 'customDirective.html' as

  2. when you use inline template both in index and inline html reflects right values from directive for obj.prop, name.firstname; but originalBill doesn't get the value ?

    Answer: Because you didn't mention scope originalBill:'=' in directive.

  3. Why can't i retrieve applyTest value from scope?

    answer: You have to correct name as apply-test="applyTest" instead of applyTest="applyTest"

You can check working code here.

customDirective.html

    <div>
      <h4 style="color:blue"> ** Custom Directive ** </h4>
      <table style="width:50%">
      <tr>
        <th>Country</th>
        <th>Person</th>
        <th>Money</th>
        <th>Original Money</th>
        <th>Testing Apply </th>
      </tr>
      <tr>
        <td>{{obj.prop}}</td>
        <td>{{name.firstname}}</td>
        <td>{{bill}}</td>
        <td>{{originalBill}}</td>
        <td>{{applyTest}} </td>
      </tr>
    </table>
    </div>

Upvotes: 1

georgeawg
georgeawg

Reputation: 48968

Attribute names need to be in kebab-case, not camelCase:

<!-- ERRONEOUS
<pass-object obj="obj" name="name" bill="bill" 
             originalBill="originalBill" applyTest="applyTest">
</pass-object>
-->

<!-- CORRECT -->
<pass-object obj="obj" name="name" bill="bill" 
             original-bill="originalBill" apply-test="applyTest">
</pass-object>

For more information, see AngularJS Developer Guide - Directive Normalization


Also don't do $apply in a linking function:

link: function(scope, element, attrs){
  scope.name = { firstname: "Tom" };
  scope.obj = { prop: "USA" };
  scope.bill="$4000";

  //DONT use $apply here
  //scope.$apply(function() {
    scope.applyTest= "New Value";
  //});
}

At any point in time there can be only one $digest or $apply operation in progress. This is to prevent very hard to detect bugs from entering your application.

This error can be seen in the debug console.

For more information, see AngularJS Error Reference - $rootScope:inprog

Upvotes: 1

Related Questions