Angularjs directive binds a name attribute to a template element

I am trying to create a wrapper directive over select, and I am trying to assign a name attribute to select

directive

<form name=myform> <selectformfield label="Select Orders" id="id_1" name="orderselection" selectedval="obj.order" options="Orders" /> </form> 

I have my directive defined as

 mainApp .directive( 'selectformfield', function() { return { restrict : 'E', transclude : true, scope : { label : '@', id : '@', selectedval : '=', options : '=', name: '=' }, template : "<select class='form-control' ng-model='selectedval' name='{{name}}' ng-options='item as item.name for item in options' required><option value=''>-- select --</option></select>" }; }); 

I try to access the select name attribute via myform in the controller, something like console.log ($ scope.myForm.orderselection), and I get undefined

If I have a hardcode name in the directive, then I can access the console.log attribute ($ scope.myForm.orderselection)

I miss nothing. Should I do compilation or something else?

+7
javascript angularjs
source share
2 answers

Khanh TO is correct in that you need to set up your name correctly when trying to access your isolated area. Here is a working example of what I think you are trying to accomplish. I added comments to the code in which I changed what you had.

plunker

JavaScript:

 var app = angular.module('plunker', []) .controller('MainCtrl', function ($scope, $log) { $scope.model = { person: { name: 'World' }, people: [{ name: 'Bob' }, { name: 'Harry' }, { name: 'World' }] }; }) .directive('selectformfield', function ($compile) { return { restrict: 'E', replace: true, // Probably want replace instead of transclude scope: { label: '@', id: '@', selectedval: '=', options: '=', name: '@' // Change name to read the literal value of the attr }, // change name='{{ name }}' to be ng-attr-name='{{ name }}' to support interpolation template: "<select class='form-control' ng-model='selectedval' ng-attr-name='{{name}}' ng-options='item as item.name for item in options' required><option value=''>-- select --</option></select>" }; }); 

HTML:

 <body ng-controller="MainCtrl"> <p>Hello {{ model.person.name}}!</p> <form name='myForm'> <label for='orderselection'>Say hello to: </label> <selectformfield label="Select Orders" id="id_1" name="orderselection" selectedval="model.person" options="model.people"></selectformfield> <p ng-class='{valid: myForm.$valid, invalid: myForm.$invalid }'>The form is valid: {{ myForm.$valid }}</p> <p ng-class='{valid: myForm.orderselection.$valid, invalid: myForm.orderselection.$invalid }'>The people select field is valid: {{ myForm.orderselection.$valid }}</p> </form> </body> 

CSS

 .valid { color: green; } .invalid { color: red; } 
+5
source share

Accessing the DOM directly in $ scope is bad practice and should be avoided at all costs. In an MVC structure such as angular, instead of accessing the DOM (view), refer to models instead of ($ scope) to get your state and data. In your case, you bind the name of your directive to the orderselection property of your parent area. Also note that the form is an instance of FormController . An instance of a form may optionally be published to a scope using the name attribute. In your case, you create a new property in the parent scope.

You can try to access the name like this if you are in your parent area:

 console.log( $scope.myform.orderselection ); 

Or if you are in the scope of your directive.

 console.log( $scope.name); 

Since the property of your scope name directive is associated with the property of the parent orderselection , you need to assign a value to the property of the parent scope or it will be undefined. Like this:

 $scope.myform.orderselection = "orderselection "; 

If you need to check inside your directive, since you are already binding the name attribute with orderselection . You can do it as follows:

 template : "<select class='form-control' ng-attr-name='{{name}}' ng-disabled='[name].$invalid' .../> 
0
source share

All Articles