简体   繁体   English

嵌套指令中的 AngularJS 双向数据绑定

[英]AngularJS Two-way Data Binding in Nested Directives

Please let me know if you need more information or want me to clarify anything.如果您需要更多信息或希望我澄清任何事情,请告诉我。 I have tried a lot of different things to figure this out but haven't found a solution.我尝试了很多不同的方法来解决这个问题,但还没有找到解决方案。

I'm relatively new to angularJS and I am trying to build an app with several layers of data.我对 angularJS 比较陌生,我正在尝试构建一个具有多层数据的应用程序。 I have some basic user information stored in the scope of the body on controller PageController.我有一些基本的用户信息存储在控制器 PageController 的主体范围内。 I then have a settings form that loads in using $routeParams (with controller SettingsController) that includes a couple of custom directives for templating purposes.然后我有一个使用 $routeParams(带有控制器 SettingsController)加载的设置表单,其中包含几个用于模板目的的自定义指令。 Since the directives are nested, I am using transclusion to load the second one inside of the first.由于指令是嵌套的,我使用嵌入来加载第一个内部的第二个。 This all seems to be working alright.这一切似乎都正常。

My problem is that I am trying to reference the field user.firstname from within the innermost directive and want to use two-way databinding to allow changes made to the textbox to cause the value at the PageController scope to change as well.我的问题是我试图从最里面的指令中引用字段user.firstname并希望使用双向数据绑定来允许对文本框所做的更改以导致 PageController 范围内的值也发生更改。 I know that a lot of these kinds of problems are caused by using primitives in ng-model, but I have tried putting everything within an extra object so that I trigger prototypal inheritance to no avail.我知道很多这类问题是由在 ng-model 中使用原语引起的,但我尝试将所有内容放在一个额外的对象中,以便触发原型继承无济于事。 What am I doing wrong here?我在这里做错了什么?

Here's a JSFiddle of my code, stripped down as much as possible to isolate the problem.这是我的代码的JSFiddle ,尽可能精简以隔离问题。 In this example, if I type in the outside textbox, which is directly on the PageController scope, it will modify the inner textbox until that textbox is modified, upon which the connection is broken.在这个例子中,如果我输入直接在 PageController 作用域上的外部文本框,它将修改内部文本框,直到该文本框被修改,然后连接断开。 This seems just like the problem of using primitives as described in other questions, but I can't figure out where the issue is here.这似乎就像其他问题中描述的使用原语的问题,但我无法弄清楚问题出在哪里。

HTML: HTML:

<body class="event-listing" ng-app="app" ng-controller="PageController">
    <div class="listing-event-wrap">
        <input type="text" ng-model="user.firstname" />
        <div ng-controller="SettingsController">
            <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}">
                <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" value="user.firstname"></div>
            </section>
        </div>
    </div>
</body>

Angular Directives:角度指令:

app.directive('formrow', function() {
return {
    scope: {
            label: "@label",
            type: "@type",
            value: "=value" 
    },
    replace: true,
    template: '<div class="form-row">' + 
            '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
            '<div class="form-entry" ng-switch on="type">' + 
                '<input type="text" ng-model="value" data-ng-switch-when="textInput" />' + 
            '</div>' + 
        '</div>'
}
});
app.directive('block', function() {
return {
    scope: {
            title: "@title",
            description: "@description" 
    },
    transclude: true,
    replace: true,
    template: '<div class="page-block">' +
            '<h2 data-ng-show="title">{{title}}</h2>' + 
            '<p class="form-description" data-ng-show="description">{{description}}</p>' + 
            '<div class="block-inside" data-ng-transclude></div>' + 
            '</div>'
}
});

Angular Controllers:角度控制器:

app.controller("PageController", function($scope) {
    $scope.user = {
        firstname: "John"
    };
});
app.controller("SettingsController", function($scope) {
    $scope.data = {
        updateInfo: {
            title: "Update Your Information",
            description: "A description here",
            labels: {
                firstname: "First Name"
            }
        }
    }
});

I'm sorry for the previous code.我很抱歉之前的代码。 Try this instead: http://jsfiddle.net/CxNc2/2/试试这个: http : //jsfiddle.net/CxNc2/2/

Instead of passing the actual value, I'm now passing the object + a pointer to the correct value inside.我现在没有传递实际值,而是传递对象 + 指向内部正确值的指针。 I added 'refobject' here:我在这里添加了“refobject”:

<body class="event-listing" ng-app="app" ng-controller="PageController">
    <div class="listing-event-wrap">
        <input type="text" ng-model="user.firstname" />
        <div ng-controller="SettingsController">
            <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}">
                <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" refobj='user' value="firstname"></div>
            </section>
        </div>
    </div>
</body>

and I added refobj + value here:我在这里添加了 refobj + value:

app.directive('formrow', function() {
    return {
        scope: {
            label: "@label",
            type: "@type",
            value: "@value",
            refobj: "="
        },
        replace: true,
        template: '<div class="form-row">' + 
            '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
            '<div class="form-entry" ng-switch on="type">' + 
        '<input type="text" ng-model="refobj[value]" data-ng-switch-when="textInput" />' + 
            '</div>' + 
        '</div>'
    }

Since the textbox in the directive uses a primitive instead of an object for its model ( ng-model="value" rather than ng-model="someobj.somevalue" ), its model is created only on the local scope and the parent does not have access to it.由于指令中的文本框对其模型使用原语而不是对象( ng-model="value"而不是ng-model="someobj.somevalue" ),它的模型仅在本地范围内创建,而父级则这样做无法访问它。

The fix is to define the directive textbox model using the dot rule as an object property:解决方法是使用点规则作为对象属性定义指令文本框模型:

ng-model="value.firstname"

Then pass the whole user object into the directive instead of just the primitive property:然后将整个user对象传递到指令中,而不仅仅是原始属性:

<div formrow ... value="user"></div>

Here is a demo这是一个演示

The problem is caused by ng-switch , From the doc Understanding scope from git.问题是由ng-switch引起的,来自 git 的文档理解范围

ng-switch scope inheritance works just like ng-include. ng-switch 作用域继承就像 ng-include 一样工作。 So if you need 2-way data binding to a primitive in the parent scope, use $parent, or change the model to be an object and then bind to a property of that object.因此,如果您需要对父作用域中的原语进行 2 向数据绑定,请使用 $parent,或者将模型更改为对象,然后绑定到该对象的属性。 This will avoid child scope hiding/shadowing of parent scope properties.这将避免父范围属性的子范围隐藏/阴影。

so if you type some text in the textbox.所以如果你在文本框中输入一些文本。 below code will be executed for the ng-switch scope.下面的代码将在ng-switch范围内执行。

$scope.value="the text you typed"

So it will not consult the prototype chain to search value .this will created a new property for ng-switch scope.所以它不会参考原型链来搜索value将为ng-switch范围创建一个新属性。

How to testify it ?如何作证?

If you change value to $parent.value .如果您将value更改为$parent.value everything will work fine.一切都会好起来的。 because in the ng-switch for the primitive type (angularjs would recognize the value as primitive type if there is no dot ) $parent will refer to formrow directive scope.因为在原始类型的ng-switch中(如果没有点,angularjs 会将value识别为原始类型) $parent将引用formrow指令范围。

Try to remove the ng-switch or do as the doc says.尝试删除ng-switch或按照文档说的做。 the problem will disappear.问题就会消失。

And more important, the document recommend us always use a dot .更重要的是,该文档建议我们始终使用点. to refer the model when apply a bi-directional binding.在应用双向绑定时引用模型。

If I said something wrong .如果我说错了。 Please kindly correct me and make it right .thanks.请纠正我并使其正确。谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM