angularjsangularjs-directiveangular-ngmodelangular-controller

AngularJS how to use ng-model inside a custom directive tag, setting the controller dynamically?


I started in Angular recently, so I have some questions.

My problem:
I created a directive that I will use in many 'pages' with different controllers in each situation, for example.
Now I can set the controller dynamically well, this problem is solved!
But, in each directive instance, I want to define what is the variable to be changed in the controller, like the ng-model. If I put directly inside the tag in template it works, but I need it dynamically.

DIRECTIVE:

app.directive('mySelectPicker', function () {
var ddo = {};
    ddo.restrict = 'E';
    ddo.templateUrl = 'js/directives/views/my-select-picker.html';

    ddo.scope = {};
    ddo.controller = "@";
    ddo.name = "controllerName";

    return ddo;
});

MY-SELECT-PICKER.HTML:
OBS1: (ng-repeat is working perfectly with values in the times controllers' array) OBS2: If I put the ng-model in the select tag, it works, but will be static!

<select>
    <option value="{{time.value}}" ng-repeat="time in times" >{{time.text}}</option>
</select>

CONTROLLER:

app.controller('MyController', function($scope, moment){
    $scope.times = []; //array with the options
    $scope.val1 = '';
    $scope.val2 = '';
});

USING THE DIRECTIVE:

<my-select-picker controller-name="MyController" **ng-model="val1"**></my-select-picker>
<my-select-picker controller-name="MyController" **ng-model="val2"**></my-select-picker>

In resume, I need to define the ng-model in each <my-select-picker> to define what is the variable in the controller. How it is possible?


Solution

  • You have created isolated scope for your directive, so you can't access the parent scope your controller directive where directive tag has been placed, so you need to to pass the options list & model name to your directive.

    Don't use ng-model as an attribute, because there is no any sense to ues ng-model attribute on directive element, as its not input element. Instead you could name that attribute as model & list then define that model & list attribute inside your isolated of directive. This both the property will be using = so that it can perform two way binding easily. Also you could use ng-options instead of ng-repeat options rendering, because ng-options has ability bind object to ng-model on selection.

    HTML

    <my-select-picker list="times" controller-name="MyController" model="val1"></my-select-picker>
    <my-select-picker list="times" controller-name="MyController" model="val2"></my-select-picker>
    

    Directive

    ddo.scope = {
       model: '=',
       list: '='
    };
    

    my-select-picker.html

    <select ng-model="model" ng-options="l.value as l.text for l in list"></select>