当表单在Angular的指令中时如何获取表单数据?

时间:2013-11-20 13:50:40

标签: angularjs angularjs-directive angularjs-scope

我有这个模板:

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

这是指令:

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();
                }
            })
        }
    }
}]);

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

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

按下提交按钮后,我希望数据在我的控制器中可用。

我认为由于隔离范围,数据不可用,但我不确定。我需要做什么才能将数据从指令恢复到我的控制器中?

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

编辑:

这是Fiddle

1 个答案:

答案 0 :(得分:3)

我认为原因是对范围如何运作的误解(特别是在进行翻译时)。

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

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

由于<my-popup> 转换了其内容,因此上述范围是MyCtrl的范围,即使在指令的内容中也是如此。内容是指<input> NOT 指令模板,即<div><form ...代码。

因此暗示model(在ng-model="model.Name"中使用)是MyCtrl范围内的属性,formSubmitted()也是如此。由于两者都是同一范围的成员,因此您无需将模型作为参数传递;你可以这么做:

(在模板中:)

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

(控制器:)

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

指令代码中还有另一个错误:

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

变量model(不是名称model:)未定义!它是范围的属性,因此如果范围未被隔离,您将有机会。由于该指令的孤立范围,它可能与我甚至不打算写的可怕的解决方法一起工作:)

幸运的是,您不需要该指令来了解外部范围内发生的事情。该指令有一个函数,用于显示表单和提交按钮,并在单击提交按钮时调用回调。因此,以下内容不仅适用于此示例,而且在概念上也是正确的(指令并不关心它外面发生了什么):

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

请参阅小提琴:http://jsfiddle.net/PRnYg/


顺便说一下:你正在使用Angular v1.0.1。这是 WAAAAY 太老了,认真考虑升级!!!如果您执行升级,请将结束</div>添加到模板:<div ng-transclude></div>