angularjs指令绑定名称属性到模板元素

时间:2013-10-19 02:30:58

标签: javascript angularjs

我正在尝试在select上创建一个包装器指令,我正在尝试将“name”属性分配给select

指令

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

我的指令定义为

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>"

                };
            });

我试图通过控制器中的myform访问select的name属性,比如console.log($ scope.myForm.orderselection),我得到了未定义的

如果我在指令中对名称进行硬编码,那么我就可以访问属性console.log($ scope.myForm.orderselection)

我在这里遗漏了什么。我必须做任何后期编译或其他什么吗?

2 个答案:

答案 0 :(得分:5)

Khanh TO是正确的,因为您需要在尝试通过隔离范围访问时正确设置您的名称。以下是我认为您要完成的工作示例。我已经在代码中添加了注释,我已经改变了你的内容。

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;
}

答案 1 :(得分:0)

直接在$ scope中访问DOM是不好的做法,应该不惜一切代价避免。在像angular这样的MVC结构中,不是访问DOM(视图)来获取其状态和数据,而是访问模型($ scope)。在您的情况下,您将指令的名称绑定到父作用域的orderselection属性。另请注意,表单是FormController的实例。可以选择使用name属性将表单实例发布到作用域中。在您的情况下,您在父作用域上创建一个新属性。

如果您在父范围内,可以尝试访问此名称:

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

或者如果你在指令范围内。

console.log( $scope.name);

由于scope指令name属性绑定到父作用域orderselection属性,因此需要为父作用域属性赋值,否则它将是未定义的。像这样:

$scope.myform.orderselection = "orderselection ";

如果您需要在指令中进行验证,因为您已将name属性与orderselection绑定。你可以这样做:

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