0

I have a directive that saves in a model in the Controller. It is a "text-button" (as per requirements) which is just a read-only textbox. There are three text-buttons per "Line" and 13 "Lines".

I need to pull up a selection modal and load some data in depending on what was clicked, so that a new selection can be made.

Although the model on the controller is changed, I don't know what was changed by the time the selection modal pops up.

Model:

$scope.Lines = {
    "eg1": { one: '', two: '', three: '' },
    "eg2": { one: '', two: '', three: '' },
    "eg3": { one: '', two: '', three: '' },
    "eg4": { one: '', two: '', three: '' },
    ... 9 more ...
};

Directive:

.directive('textButton', function () {
    return {
        restrict: 'E',
        require: 'ngModel',
        link: function ($scope, elm, attrs, ctrl) {
            elm.on('click', function () {
                $scope.popModal(this); //<--I want the ng-model here!
            });
        },
        template: '<input type="text" readonly="readonly" class="form-control" />'
    };
});

View:

<ul>
    <li> <text-button ng-model="Lines.eg1.one"></text-button> </li>
    <li> <text-button ng-model="Lines.eg1.two"></text-button> </li>
    <li> <text-button ng-model="Lines.eg1.three"></text-button> </li>
<ul>
<ul>
    <li> <text-button ng-model="Lines.eg2.one"></text-button> </li>
    <li> <text-button ng-model="Lines.eg2.two"></text-button> </li>
    <li> <text-button ng-model="Lines.eg2.three"></text-button> </li>
<ul>
... 11 more ...

I've looked at $watch and $scope.watch, but nothing seems to be able to tell me what in a particular model has changed.

https://stackoverflow.com/a/15113029/1913371

Community
  • 1
  • 1
Beshoy Hanna
  • 611
  • 2
  • 9
  • 29

2 Answers2

2

In the end, you need to isolate the scope of your directive so you have a chance to get to the ngModel of each line:

scope: {
   ngModel: '@',
   popModal: '='
}

then you can use it in your callback:

elm.on('click', function () {
    $scope.popModal($scope.ngModel); //<--you get the ng-model here!
});

However, this means you also lose access to popModal() which I guess is defined in the controller scope. To fix this, you need to hand it in as a second parameter (I named it pop-modal):

<text-button ng-model="Lines.eg1.one" pop-modal="popModal"></text-button>

Tying it all together, here's a JSBin using Angular 1.2 (although you really should get away from that).

Johannes Jander
  • 4,974
  • 2
  • 31
  • 46
  • Ahhh... `scope:{}` was what I was missing. You were right about popModal being a function in the controller scope, sorry for not clarifying that. Also, the project requires support for IE8. :( – Beshoy Hanna Mar 10 '16 at 12:42
  • I do have a quick question/concern: How come `pop-modal="popModal"` does not work in the `template`? – Beshoy Hanna Mar 10 '16 at 12:52
  • Because after creating an isolate scope, the template is compiled on that isolated directive scope which does not know anything about the controller scope. It would be kind of messy if you could define templates the reference something in the parent scope without you knowing it. I am sure with the "function returning function" capabilities of JS, you could to it regardless. But I'd go with `$scope.$emit('popModal', $scope.ngModel);` in the click handler and `$scope.$on('popModal', function(model)` in the controller to communicate click without having to write it in every occurence of directive – Johannes Jander Mar 11 '16 at 22:22
0

If you are using AngularJs 1.3+, you can use 'controllerAs' in the directive definition object. Then create a controller to do popModal.

sam
  • 1,937
  • 1
  • 8
  • 14