0

I'm trying to have Two-Way binding on a directive.

I can't use the scope on the directive (multiple directives on element), so I'll have to do it in the compile(){...} function

This is a simplified version of the directive so far:

.directive('myDialog', function() {
      return {
        restrict: 'E',
        templateUrl: 'my-dialog.html',
        compile: function(tElement, tAttrs, transclude) {
          return function($scope, $element, $attributes) {
            $scope.label = $scope.$eval($attributes.label);

            // when I set the label on something this should update the parent
            $scope.label = "test";
          }
        }
      };

So how can I make it that when I change the lable in my directive it updates the value in the main application, and visa versa

Plunker for testing: http://plnkr.co/edit/lARCrGD5FsnOWQZrahIl?p=preview

UPDATE: here is the actual setup with all the logic for what I'm trying to archieve: http://codepen.io/cskiwi/pen/eJryqK?editors=1010

On line 101 i want to set the testing var on true, later one I'm also going to set to testing var on false outside that directive

UPDATE2: Got something, that is maybe something to lookinto:

  return {
        restrict: "A",
        require: ["^mdChips", "^chipBar"],
        controller: "chipBarController",
        controllerAs: "chipBarController",
        bindToController: {
            activated: "="
        },
        // rest of the code

this is allowing to set the activated var to true from in the directive; but now I can't set the value from my appCtrl back to false

11
  • 1
    what's the question here? Commented Jan 29, 2016 at 13:21
  • 3
    also, that directive doesn't have an isolated scope. Commented Jan 29, 2016 at 13:22
  • 1
    use scope in your link fn not $scope, if your dont want isolate scope and without 2 way binding (=) , you have explicit use scope.$parent and change that value Commented Jan 29, 2016 at 13:25
  • 1
    I've read the comments, potential answers, your responses, and looked at the code. It's not clear why you continue to suggest that you can't use the solutions provided so far, but what is clear from the codepen is that you are mixing up controllerAs and $scope, and trying to use both at the same time, which will be more trouble than it's worth. I'm going to try to decipher the codepen and offer some advice, but I can't guarantee anything. Commented Jan 29, 2016 at 14:58
  • 1
    in fact, there is a lot of unusual things going on with your codepen; in particular, your use of if statements to change templates, along with some rather unusual references to things like $$replacedScope.... It seems like there are multiple ways that this could be refactored, and once refactored, your current issue would be easier to deal with. Commented Jan 29, 2016 at 15:09

3 Answers 3

1

her is a working plunker with data binding http://plnkr.co/edit/qtfEPfbNTZHHUEBhGYye?p=preview

there is a lot of detailled reading over the net

http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope

http://www.bennadel.com/blog/2726-isolate-scope-two-way-data-binding-is-eventually-consistent-in-angularjs.htm ...


You should create a scope variable for your directive to let the directive know which variable to bind one

HTML

  <div ng-controller="Controller">
    {{email}} &lt;== should become test on launch

    <my-dialog email="email"></my-dialog>

    <button ng-click="click()">click</button>  &lt;== should turn both in tst
  </div>

template my-dialog.html

<div class="alert">
      email is :- {{email}}!
</div>

JS

  angular.module('docsTransclusionExample', [])
    .controller('Controller', ['$scope', function($scope) {
      $scope.email = '[email protected]';

      $scope.click = function(){
        $scope.email = "tst";
      }
  }])
  .directive('myDialog', function() {
      return {
        restrict: 'E',
        scope : { // this create an isolated scope
           email:'='   // the email attribute is binded two way with '=', there is also '@' and '&'
        },
        templateUrl: 'my-dialog.html'

      };
    });
Sign up to request clarification or add additional context in comments.

2 Comments

like said before, I can't use the scope {}
the reason why I can't use the scope is the codepen in the first post
0

The update2 was actually fixing the issue.

    controllerAs: "chipBarController",
    bindToController: {
        activated: "="
    },

did everything it needed,

had just a typo in my code

Thanks Everyone who helped, especially @Claies

Comments

0

I agree with coments saying that you have probably a design problem but 'ill give you a way to do what you want.

Use ng-model directive and controller then with that you can read/watch for change/change the value :)

See tutorial here : https://www.nadeau.tv/using-ngmodelcontroller-with-custom-directives/

EDIT : well if you can use proper binding i have a quite dirty and tricky way of doing it : Based on this documentation : https://docs.angularjs.org/api/ng/function/angular.element

Add an attribute which will contains the field path as a string in controller scope (a.b.c if it's in $scope.a.b.c) like this

Get the parent element of your directive with angular.element() and get his scope with the scope method (in the documentation). Then call the $eval method if this scope like this to read theScope.$eval(attrs.fieldsPath); and with the $eval you should be able to update values too with theScope.$eval(attrs.fieldsPath+='myValue'). If it doesn't work you'd have to split your string with '.' and navigate through the scope object to write on the right field.

var value = $scope;
var tab  = attrs.fieldPath.split('.');
for(i = 0; i < tab.length && value; i++){
    value = value[tab[i]];
}

1 Comment

I'm already using the ng-model for something else, see the codepen in the first post

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.