8

I am trying create a wrapper directive over select and I am trying to assign the 'name 'attribute to the 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 am trying to access the select's name attribute through myform in the controller something like console.log($scope.myForm.orderselection) and I get undefined

If I hardcode the name in the directive then I am able to access the attribute console.log($scope.myForm.orderselection)

I am missing anything here. Do I have to do any post compile or something ?

2 Answers 2

5

Khanh TO is correct in that you need to setup your name correctly when trying to access to through your isolated scope. Here is a working example of what I believe you are trying to accomplish. I've added comments to the code where I've 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;
}
Sign up to request clarification or add additional context in comments.

Comments

0

Accessing the DOM directly in $scope is bad practice and should be avoided at all costs. In MVC structure like angular, instead of accessing the DOM (view) to get its state and data, access the models instead ($scope). In your case, you're binding the name of your directive to the orderselection property of your parent scope. Also notice that a form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute. In your case, you create a new property on the parent scope.

You could try accessing the name like this if you're in your parent scope:

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

Or if you're in your directive scope.

console.log( $scope.name);

Because your scope directive name property binds to your parent scope orderselection property, you need to assign a value to your parent scope property or it will be undefined. Like this:

$scope.myform.orderselection = "orderselection ";

If you need to do validation inside your directive, since you already bind the name attribute with the orderselection. You could do it like this:

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

2 Comments

I actually trying do some form validation and I would like to assign a name to the select field so that I get its error state ng-disabled="myForm.orderselection.$invalid".
@sam: I did not know that you need to do validation. Check updated answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.