当表单在Angular中的指令中时如何获取表单数据? [英] How to get the form data when the form is in a directive in Angular?

查看:22
本文介绍了当表单在Angular中的指令中时如何获取表单数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个模板:

<form data-ng-submit="submit()"><div class="modal-body" data-ng-transclude>

<div class="modal-footer"><button type="button" class="btn btn-default" data-ng-click="visible = false">Annuleren</button><button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Maken</button>

</表单>

这是指令:

app.directive("modalPopup", [function() {返回 {限制:'E',templateUrl: 'Utils/ModalPopup',范围: {标题: '@',onSubmit: '&',可见:'='},转置:真实,链接:函数(范围、元素、属性){var container = $("#popupModal");scope.submit = 函数(新组){scope.onSubmit(newGroup);}scope.hide = 函数 () {container.modal('隐藏');}scope.show = 函数 () {container.modal('show');}scope.$watch('visible', function (newVal, oldVal) {if (newVal === true) {范围.show();}别的 {范围.隐藏();}})}}}]);

如您所见,我已经在指令中声明了我的 form 标记,并且我还使用了 transclude 来确定我的表单的外观.现在我有这个:

<div class="row"><div class="col-md-3">Kopieren van:</div><div class="col-md-8"><select class="form-control" data-ng-model="newGroup.Year"><option value="">Nieuw jaar</option><option data-ng-repeat="year in years" value="{{year.Id}}">{{year.Name}}</option></选择>

<div class="row"><div class="col-md-3">Naam</div><div class="col-md-8"><input type="text" class="form-control" data-ng-model="newGroup.Name"/>

</modal-popup>

当按下提交按钮时,我希望数据在我的控制器中可用.

我问由于范围孤立,数据不可用,但我不确定.我需要做什么才能将指令中的数据取回控制器?

PS:我了解 angular-ui 和 angularstrap,但我这样做是为了了解 Angular.

这是一个小提琴

解决方案

我认为原因是对作用域如何工作的误解(尤其是嵌入).

让我们从这段代码开始(来自小提琴):

<my-popup on-submit="formSubmitted(model)"><input type="text" ng-model="model.Name"/></my-popup>

由于<my-popup> transcludes 其内容,上面的作用域是MyCtrl的作用域,即使在指令的内容中.我所说的内容是指 NOT 指令模板,即

代码.

因此暗示model(在ng-model="model.Name"中使用)是MyCtrl作用域的一个属性代码>,和 formSubmitted() 一样.由于两者都是同一作用域的成员,因此您无需将模型作为参数传递;你可以这样做:

(在模板中:)

<my-popup on-submit="formSubmitted()"><!-- 没有 `model` 参数 -->

(控制器:)

function MyCtrl($scope) {//我喜欢显式声明 $scope 成员,//虽然没有它也能工作(charlietfl 评论)$scope.model = {};$scope.submittedValue = null;$scope.formSubmitted = function() {//另一个错误在这里;`model` 始终是 `$scope` 的成员//对象,不是局部变量$scope.submittedValue = $scope.model.Name;}}

另一个错误在指令代码中:

link: 函数(作用域、元素、属性){scope.submit = function(){scope.onSubmit({model: 模型});}}

变量model(不是名称model:)未定义!它是 parent 作用域的一个属性,所以如果作用域不是孤立的,你就有机会.由于指令的范围是孤立的,它可能会使用一种我什至不考虑编写的糟糕的解决方法:)

幸运的是,您不需要指令来了解外部作用域中发生的事情.该指令有一个功能,用于显示表单和提交按钮,并在单击提交按钮时调用回调.所以下面的内容不仅对于这个例子来说足够了,而且在概念上也是正确的(指令不关心它外面发生了什么):

link: 函数(作用域、元素、属性){scope.submit = function(){范围.onSubmit();}}

看小提琴:http://jsfiddle.net/PRnYg/

<小时>

顺便说一下:您使用的是 Angular v1.0.1.这WAAAAY太旧了,认真考虑升级!!!如果您确实升级,请将结束的</div>添加到模板中:<div ng-transclude></div>.

I have this this template:

<div class="modal" id="popupModal" tabindex="-1" role="dialog" aria-labelledby="createBuildingLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                <h4 class="modal-title" id="createBuildingLabel">{{ title }}</h4>
            </div>
            <form data-ng-submit="submit()">
                <div class="modal-body" data-ng-transclude>

                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-ng-click="visible = false">Annuleren</button>
                    <button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-save"></span>Maken</button>
                </div>
            </form>
        </div>
    </div>
</div>

and here's the directive:

app.directive("modalPopup", [function () {
    return {
        restrict: 'E',
        templateUrl: 'Utils/ModalPopup',
        scope: {
            title: '@',
            onSubmit: '&',
            visible: '='
        },
        transclude: true,
        link: function (scope, element, attributes) {
            var container = $("#popupModal");

            scope.submit = function (newGroup) {
                scope.onSubmit(newGroup);
            }

            scope.hide = function () {
                container.modal('hide');
            }

            scope.show = function () {
                container.modal('show');
            }

            scope.$watch('visible', function (newVal, oldVal) {

                if (newVal === true) {
                    scope.show();
                }
                else {
                    scope.hide();
                }
            })
        }
    }
}]);

As you can see I have declared my form tag inside the directive and I also use transclude to determine how my form is going to look like. For now I have this:

<modal-popup title="Nieuwe groep aanmaken" data-on-submit="createGroup()" visible="showAddGroupForm">
    <div class="row">
        <div class="col-md-3">Kopieren van:</div>
        <div class="col-md-8">
            <select class="form-control" data-ng-model="newGroup.Year">
                <option value="">Nieuw jaar</option>
                <option data-ng-repeat="year in years" value="{{year.Id}}">{{year.Name}}</option>
            </select>
        </div>
    </div>
    <div class="row">
        <div class="col-md-3">Naam</div>
        <div class="col-md-8">
            <input type="text" class="form-control" data-ng-model="newGroup.Name" />
        </div>
    </div>
</modal-popup>

When the submit button is pressed, I want the data to be available in my controller.

I ques the data isn't available because of the isolated scope, however I'm not sure. What do I need to do to get the data back from the directive into my controller?

PS: I know about angular-ui and angularstrap, but I'm doing this to learn about Angular.

EDIT:

Here's a Fiddle

解决方案

I think the cause is a misunderstanding about how scopes work (especially with transclusion).

Let's start with this code (from the fiddle):

<div ng-controller="MyCtrl">
    <my-popup on-submit="formSubmitted(model)">
        <input type="text" ng-model="model.Name"/>    
    </my-popup>
</div>

Since <my-popup> transcludes its content, the scope above is that of MyCtrl, even in the content of the directive. By content I mean the <input>, NOT the directive template, i.e. the <div><form ... code.

Therefore it is implied that model (as used in ng-model="model.Name") is a property of the scope of MyCtrl, as is formSubmitted(). Since both are members of the same scope, you do not need to pass the model as argument; you could just do:

(in the template:)

<my-popup on-submit="formSubmitted()"><!-- no `model` argument -->

(the controller:)

function MyCtrl($scope) {
    // I like declaring $scope members explicitly,
    // though it can work without it (charlietfl comments)
    $scope.model = {}; 
    $scope.submittedValue = null;
    $scope.formSubmitted = function() {
        // another bug was here; `model` is always a member of the `$scope`
        // object, not a local var
        $scope.submittedValue = $scope.model.Name;
    }
}

Another bug is in the directive code:

link: function(scope, element, attributes){
    scope.submit = function(){
        scope.onSubmit({model: model});
    }
}

The variable model (not the name model:) is undefined! It is a property of the parent scope, so you would have a chance if the scope was not isolated. With the isolated scope of the directive, it may work with an awful workaround that I am not even considering to write :)

Luckily, you do not need the directive to know about things happening in the external scope. The directive has one function, to display the form and the submit button and invoke a callback when the submit button is clicked. So the following is not only enough for this example, but also conceptually correct (the directive does not care what is happenning outside it):

link: function(scope, element, attributes){
    scope.submit = function(){
        scope.onSubmit();
    }
}

See the fiddle: http://jsfiddle.net/PRnYg/


By the way: You are using Angular v1.0.1. This is WAAAAY too old, seriously consider upgrading!!! If you do upgrade, add the closing </div> to the template: <div ng-transclude></div>.

这篇关于当表单在Angular中的指令中时如何获取表单数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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