AngularJS - 模块化形式与指令 [英] AngularJS - Modular forms with directives

查看:101
本文介绍了AngularJS - 模块化形式与指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初问这个问题<一href=\"http://stackoverflow.com/questions/17513319/angularjs-transcluded-scope-with-child-scopes\">here,但我觉得我得到了超前了,并使其更加复杂比它确实是,所以我有一点明确的案文再次要求在这里。

I originally asked this question here, but I think I got ahead of myself and made it more complicated than it really is, so I'm re-asking it here with a bit clearer wording.

如何创建可重用的表单控件与指令和可重复使用的参数?像这样的:

How do you create re-usable form widgets with directives and re-useable parameters? Like this:

<form>
<special-input label-text="A Special Input" bind-to="data.special"></special-input>
<special-input label-text="Specialer" bind-to="data.moreSpecial"></special-input>
</form>

指令模板似乎并没有允许NG-模型插值。

Directive templates don't seem to allow interpolation on ng-model.

此外,还可以模块化和参数化形式的行为,这样就可以有标准的POST操作,例如?

Furthermore, can you modularize and parameterize form behavior so that you can have standard POST actions, for example?

我已经回答以下问题。根据我的实验,但我会从接受了一段时间不下来,因为我很新的角度,想从别人那里听到的。

I've answer the question below based on my experimentation, but I'll hold off from accepting it for a while, since I am very new to Angular and would like to hear from others.

推荐答案

角度来开箱即用的改进标签是的此处记载。的基本上它会在周围形式的控制器和所有在其内的标记形式的范围。所以,你这样做:

Angular comes out of the box with an improve tag that is documented here. Basically it creates a scope in the form of a controller around the form and all of the tags within it. So you do this:

<body ng-app="TestApp">
<form ng-controller="FormCtrl" name="testForm">
    <input name="firstInput" ng-model="data.first">
    <input name="secondInput" ng-model="data.second">
    <button ng-click="submit()">Submit</button>
</form>
</body>

JS:

var app = angular.app('TestApp', []);
app.controller('FormCtrl', function($scope) {
    $scope.submit = function() {
        // Form submit logic here
        console.log("Submitting the form");
        console.log($scope);
    }
})

这会为形式的范围,因为形式标记包含NG控制器标签。在范围, TESTFORM 是JavaScript对象的形式,而 testForm.firstInput 是第一个JavaScript对象输入。它看起来像这些对象也有一定的验证功能可用,在这里看到的文档。

This creates a scope for the form, since the form tag contains the ng-controller tag. Within the scope, testForm is the javascript object for the form, and testForm.firstInput is the javascript object for the first input. It looks like these objects also have some validation functionality available, see docs here.

在表格上的数据将作为在FormCtrl范围对象的数据,用钥匙第一,第二,你可以定义在控制器上的工作方法。

The data on the form will be available as an object data in the FormCtrl scope, with keys "first" and "second", and you can define methods in the controller that work on that.

您也可以把使用相同FormCtrl多种形式,而且好像角将为每个表单创建新实例,所以你不必担心污染形式彼此的数据。

You can also put multiple forms using the same FormCtrl, and it seems like Angular will create new instances for each form, so you don't have to worry about forms polluting each other's data.

现在可以假设我们有某种复杂的输入或窗口小部件是在指令实施。此示例使用两个选择框来显示一个国家的所有城市。你必须先选择一个国家,那么它会查询该州城市和填充第二个选择框。

Now lets suppose that we have some sort of complex input or widget that is implemented in a directive. This example uses two select boxes to display all cities in a state. You have to first select a state, then it'll query for the cities in that state and populate the second select box.

app.directive('citySelect', function() {
    return {
        replace: true,
        template: '<div><select ng-change="getCities()" ng-options="s.name for s in states"></select>' +
                  '<select ng-model="data.selectedCity" ng-options="c.name for c in cities"></select>',
        controller: function($scope) {
            // Omitting the logic for getCities(), but it'd go here
        }
    };
})

然后,你可以把它贴到表单标签,它会工作。由于指令不定义范围,它只会附着在FormCtrl的范围。

Then you can just stick it into the form tag, and it'll work. Because the directive doesn't define a scope, it'll just attach to the scope of the FormCtrl.

<body ng-app="TestApp">
<form ng-controller="FormCtrl" name="testForm">
    <input name="firstInput" ng-model="data.first">
    <input name="secondInput" ng-model="data.second">
    <div city-select></div>
    <button ng-click="submit()">Submit</button>
</form>
</body>

Paramaterizing指令

编辑:
因此很明显,这样做的工作:

Paramaterizing the directives

So apparently this does work:

scope: {someParameter: "="},
template: '<div><select ng-model="someParameter"></select></div>'

您只需做没有的花括号,它会绑定。我的猜测是父范围由子作用域结合someParameter,然后选择在子范围结合somParameter。

You simply do it without the curlies, and it'll bind. My guess is that the parent scope is binding to someParameter in the child scope, and the select is then binding to somParameter in the child scope.

所以,这一切的纽带作用低于手动编译是没有必要的。

So all of this below about manually compiling in the link function is not necessary.

=====

但这样做的问题是,我的citySelect指令有一个硬codeD NG-模型绑定,所以如果我创造了一些通用的部件,我不能将它的多个表单中。不幸的是这似乎并没有工作:

But the problem with this is that my citySelect directive has a hard coded ng-model binding, so if I created some sort of generic widget, I couldn't use more than one of it in a form. Unfortunately this does not seem to work:

scope: {someParameter: "="},
template: '<div><select ng-model="{{ someParameter }}"></select></div>'

这是我得到这个工作的唯一方法是在连接功能手动生成的DOM元素,但我不知道这是不可取的。我就从这个人实现AP preciate评论:

The only way that I have gotten this to work is to build the DOM element manually in a linking function, but I'm not sure if this is advisable. I would appreciate comments from anyone about this implementation:

<body ng-app="TestApp">
<form ng-controller="FormCtrl" name="testForm">
    <input name="firstInput" ng-model="data.first">
    <input name="secondInput" ng-model="data.second">
    <div city-select bind-to="data.homeCity"></div>
    <div city-select bind-to="data.workCity"></div>
    <button ng-click="submit()">Submit</button>
</form>
</body>

app.directive('citySelect', function($compile) {
    return {
        replace: true,
        template: '<div></div>',
        controller: function($scope) {
            // Omitting the logic for getCities(), but it'd go here
        }
        link: function(scope, iElem, iAttrs) {
            var html = '<div><select ng-bind="' + iAttrs['bindTo'] + '"></div>';
            iElem.replaceWith($compile(html)(scope));
        }
    };
})

的形式混合在参数

由于每个表单创建FormCtrl的不同实例,您可以重用大量的FormCtrl的功能。但你也可以使用一个表单标签的附加指令添加参数或掰开功能。例如:

Mixing in parameters on the form

Since separate instances of FormCtrl are created for each form, you can reuse a lot of the functionality in FormCtrl. But you can also use additional directives on a form tag to add parameters or break apart functionality. For example:

<form ng-controller="FormCtrl" name="testForm" post-form post-path="/path/to/resource/">

app.directive('postForm', function() {
    return {
        controller: function($scope) {
            $scope.post = function() {
                // Some generic POST behavior
            };
        },
        link: function(scope, iElem, iAttr) {
            scope.postPath = iAttr['postPath'];
        },
    };
});

然后

在窗体的范围将从FormCtrl和postForm合并范围,让一切都可以访问。在我的实验,它似乎像FormCtrl花费precedence,所以如果像$ scope.submit()在这两个FormCtrl和postForm定义,FormCtrl的将采取precedence(我认为),也许这是一个种族从异步加载条件下,我不知道。

The form's scope will then combine the scope from FormCtrl and postForm, so that everything is accessible. In my experimentation, it seems like the FormCtrl takes precedence, so if something like $scope.submit() is defined in both FormCtrl and postForm, FormCtrl's will take precedence (I think), maybe this is a race condition from asynchronous loading, I don't know.

而不是使用NG-控制器的,我想你也可以使用范围:真正的的混入指令(postForm),或者更安全,范围:{}

Instead of using ng-controller, I think you can also use scope:true on the mixin directive (postForm), or perhaps more safely, scope: {}.

这篇关于AngularJS - 模块化形式与指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆