角度模型的范围不能在子DOM元素中变量?

时间:2014-08-08 23:35:45

标签: angularjs

我有这个标记:

<div data-ng-model="currentUser.attributes">
    <div>{{username}}</div>
</div>

这是我控制器的精简版:

$scope.username = "Alice";
$scope.currentUser = {
    attributes: {
        username: "Bob"
    }
};

我希望显示Bob,但我得到Alice。如果我使用它,它的工作正常:

{{currentUser.attributes.username}}

但是我不希望每次想要访问某些内容时都要限制此变量的属性。如何让元素存在于currentUser.attributes

的范围内

4 个答案:

答案 0 :(得分:2)

虽然我认为你不应该这样做,但这是你要求的。您可以在使用相关对象填充的数组上使用with来模仿ng-repeat。例如:

<div ng-repeat="user in [currentUser.attributes]">
    {{ user.username }}
</div>

工作人员:http://plnkr.co/edit/svwYEeWMQXjuAnLkr9Vz?p=preview

其他可能的解决方案是拥有一个服务或控制器,它具有获取属性并返回它们的功能,清理HTML的语法,并且在不破坏前端的情况下更容易更改后端内容。你的选择。

修改:我注意到您实际上希望能够{{ username }}获取相关信息,如果这真的是您想要的话,那么我建议我提出第二个提案。创建返回相关信息的函数。

<div>
    {{ getCurrentUserName() }}
</div>

$scope.getCurrentUserName = function() {
    return $scope.currentUser.attributes.username;
};

您的电话,接听或离开。

答案 1 :(得分:1)

如果您希望Bob在HTML中执行以下操作。

<div>{{current user}}</div>//IGNORE THIS

<div>{{currentUser.attributes.username}}</div>//UPDATED CORRECTED

根据澄清更新。

所以在Knockout中你这样做

<p data-bind="with: currentUser.attributes">
    <div data-bind="text: userName></div>
    <div data-bind="text: login></div>
    <div data-bind="text: bhalBlah></div>
    <div data-bind="text: yaddaYadda></div>
</p>

<script type="text/javascript">
    ko.applyBindings({
        currentUser: {
           attributes: {
                userName  : 'Bob',
                login     : 't@e',
                blahBlah  : 'ttttt',
                yaddaYadda: 'x'
           }
        }
    });
</script>

AngularJS中的相同内容是

<p ng-controller="myCtrl">
    <div>{{currentUser.attributes.userName}}</div>
    <div>{{currentUser.attributes.login}}</div>
    <div>{{currentUser.attributes.blahBlah}}</div>
    <div>{{currentUser.attributes.yaddaYadda}}</div>
</p>


<script type="text/javascript">
angular.module('myApp',[]).controller('myCtrl',function($scope){
    $scope =  {
     currentUser: {
           attributes: {
                userName  : 'Bob',
                login     : 't@e',
                blahBlah  : 'ttttt',
                yaddaYadda: 'x'
           }
    };
});
</script>

在这个问题是如何避免如何不重复**之间的完整属性路径,如下所示的角度。

  **currentUser.attributes.**userName
  **currentUser.attributes.**login
  **currentUser.attributes.**blahBlah
  **currentUser.attributes.**yaddaYadda

以下是使用ng-init查看plnkr的一种方法,它可以减少&lt; currentUser.attributes&#39;只是&#39; attr&#39;。

        

只有attr。&lt; properties&gt;重复

        {{attr.userName}}         {{attr.login}}         {{attr.blahBlah}}         {{attr.yaddaYadda}}     

另一种方法是重构对象并将其展平在$ scope上。 建议不要这样做,因为现在要将原语放在$ scope上,并使用$ scope.userName = currentUser.attributes.username扩展范围。还有你的重复&#39;代码仍然存在于Javascript中。

代替ng-init

ng-init="attr = currentUser.attributes"

您也可以在控制器中执行此操作

$scope.attr = currentUser.attributes;

答案 2 :(得分:1)

这篇文章真让我思考。我有一个关于如何使用指令完成此操作的理论。

在plnkr上提出了一个概念证明:http://embed.plnkr.co/OJDhpJ1maEdSoPvlbiRA/

如果我理解正确,您只想在结构的给定块中显示属性。

给出以下结构:

$scope.currentUser = {
    attributes: {
      username: 'Batman',
      age: '99',
      address: {
        street: 'Bat Cave'
      }
    }
  };

你希望用以下内容来缩小范围:

<div scope-with="currentUser.attributes">
    Username: {{username}}<br />
    Age: {{age}}
    <div scope-with="address">
       Street: {{street}}
    </div>
</div>

指令:

angular.module('mymodule', [])

.directive('scopeWith', function($interpolate){


  return {

    restrict: 'A',
    scope: {
      scopeWith: '='
    },
    transclude: 'element',
    compile: function(tElement, tAttrs, linker) {

      return function( scope, element, attr) {

        var childScope,
            parent = element.parent(),
            withBlock = null
        ;

        scope.$watch('scopeWith', function(val){
          childScope = scope.$new();

          angular.forEach(val, function(val, prop){
            childScope[prop] = val;  
          });


          if(withBlock) {
            withBlock.el.remove();
            withBlock.scope.$destroy();
          }

          linker(childScope, function(clone){

            withBlock = {};
            parent.append(clone);
            withBlock.el = clone;
            withBlock.scope = childScope;

          });


        }, true);

      };

    }

  };

答案 3 :(得分:0)

使用{{currentUser.username}}来显示Bob。

div上的ng-model是无关紧要的,因为它只适用于输入元素。