Search code examples
javascriptangularjsangularjs-scope

$scope and ng-model in the same directive


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


Solution

  • 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).