2

I'm trying to generate a directive that embeds an editor (form). The outer controller is able to push the "thing to edit" into the inner directive easily enough, but I'd like the outer controller to know when the form is dirty. My overall template (simplified):

<div ng-controller="outer">
   <account-editor account-id="currentID" dirty-flag="isDirty"></account-editor>
</div>

I want to be updating the isDirty flag on the "outer" controller with this directive:

directive('accountEditor',[ 'account', function(account) {
  return {
    restrict: 'E',
    scope: {
      accountId: '=',
      dirtyFlag: '='
    },
    link: function($scope, element, attr, ctrl) {
      $scope.$watch('accountId', function() {
        $scope.accountToEdit = account.getAccount($scope.accountId);
      });
      // I WANT TO WATCH THE FORM STATE, AND UPDATE dirtyFlag
    },
    template: '<form><input ng-model="accountToEdit.name"/></form>'
  };
}]);

Should I write an additional directive to put on the <form>, use an event, access the DOM directly during link, or something else?

My full code is at http://jsbin.com/amuduro/1/edit, but it includes LOTs more features.

Tony K.
  • 5,535
  • 23
  • 27
  • playing with this a bit. Here's one hugely important concept. Don't use **primitives** in scope to pass down through child scopes. Pass objects, so reference of original object is available through all the descendant scopes....`$scope.model={idx: 0, isDirty:false}`...pass `model` into directive scopes then `model.isDirty=true` from child scope will register referenced object up the tree – charlietfl Dec 11 '13 at 03:17
  • Can you explain why this statement: "Don't use primitives in scope to pass down through child scopes." I've read it before, but I'm not clear why it's an issue. – Darryl Dec 11 '13 at 03:48
  • ok....`var a={}, b=a`...`b` is not copy of `a` it is a reference. Any changes to either affects the other ( they are the same object) `var x="foo", y=x` .... being primitives `y` is copy of `x` , changing either does not affect the other. So as you go layers deep in nesting scopes....updating an object 5 layers deep will update all references back up the tree ( same object). Updating primitive is dead end at child scope – charlietfl Dec 11 '13 at 03:53
  • http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs – charlietfl Dec 11 '13 at 04:01
  • as result...any time can avoid isolated scope in directive is good to. Saw a number of `scope:{/*empty obj*/}` in your directives....can add extra un needed headaches – charlietfl Dec 11 '13 at 04:04
  • @charlietfl I'm using isolated scope for exactly what it is: a way to make a reusable component. So, I assume if I understand the system well-enough, I should be able to use it for the intended purpose: preventing namespace pollution. – Tony K. Dec 11 '13 at 16:13
  • that's fine...but is critical to understand the inheritance issues with isolated scopes – charlietfl Dec 11 '13 at 16:26
  • There _are_ no inheritance issues with isolated scopes...the inheritance issues are with NON-isolated scopes. (You can still hit them outside of it, so one could argue that my _use_ of my new directive should be using a non-primitive), but if you try it out, you'll see that my solution cannot shadow the parent, because there _is_ no parent scope....it is isolated, and the '=' creates a new two-way data binding. Yet another reason you _want_ to create a scope on this kind of directive. – Tony K. Dec 11 '13 at 16:51

1 Answers1

0

Putting a form name on the embedded for will cause the controller to be placed on the directive's scope (even if it is isolated), so the following works:

<form name='theForm'>...</form>

and then within the directive link:

  $scope.$watch('theForm.$dirty', function() {
    $scope.dirtyFlag = $scope.theForm.$dirty;
  });
Tony K.
  • 5,535
  • 23
  • 27