javascript AngularJS:如何使不属于 ng-repeat 的局部变量工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22871222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 23:55:33  来源:igfitidea点击:

AngularJS: How to make local variables work which are not part of ng-repeat

javascriptangularjsangularjs-scopeangularjs-ng-repeat

提问by bazzinga

I have an application where I am receiving a list of person objects in persons and iterating over to build a table dynamically.

我有一个应用程序,我在其中接收人员中的人员对象列表并迭代以动态构建表。

The code looks like this:

代码如下所示:

<table>
  <tr ng-repeat = "personInfo in persons">
    <td>{{personInfo.name}}</td>
    <td>{{personInfo.gender}}</td>
    <td>
      <select ng-model="selected_address" ng-options="address.placename for address in personInfo.address"></select>
      <span ng-show="make_address_editable==false;">{{selected_address.address}}</span>
      <input type="text" style="width: 22em;" ng-show="make_address_editable" ng-model="selected_address.address" />
      <input style="margin-left: 2em;" type="button" value="{{btnValue}}" ng-show="selected_address" ng-click="make_address_editable=!make_address_editable; changeBtnValue($index)"/>
    </td>
  </tr>
</table>

The part where I am stuck is how to change the value of input[type="button"] or {{btnValue}} individually for each person which edits/saves a person's address. I don't want to assign it as a property on the personInfo object as I would not need it later. In my controller I initialize the value of make_address_editable and btValue but I'm only able to control the behavior of make_address_editable on ng-click for each person. If I call a function on ng-click which changes btnValue depending on what the user clicked it changes the btnValue for each row/person.

我被卡住的部分是如何为每个编辑/保存一个人的地址的人单独更改 input[type="button"] 或 {{btnValue}} 的值。我不想将它分配为 personInfo 对象上的属性,因为我以后不需要它。在我的控制器中,我初始化了 make_address_editable 和 btValue 的值,但我只能在每个人的 ng-click 上控制 make_address_editable 的行为。如果我在 ng-click 上调用一个函数,它会根据用户单击的内容更改 btnValue,它会更改每一行/人的 btnValue。

Controller code:

控制器代码:

$scope.make_address_editable = false;
$scope.btnValue = 'Edit';
$scope.changeBtnValue = function(index){
  if ($scope.btnValue === 'Edit'){
    $scope.btnValue = 'Save';
  }
  else{
    $scope.btnValue = 'Edit';
  }
}

I don't know how to use index in the method to change btnValue for each person in the table.

我不知道如何在方法中使用索引来更改表中每个人的 btnValue。

Any help would be much appreciated.

任何帮助将非常感激。

Thanks!

谢谢!

采纳答案by Patrick

There should be no problem including a btnValue within the personInfo object as this is a ViewModel and you are really driving the view (value of button) based on what is in that model. You may not be using it later in terms of using that value when persisting the person to a datastore, but your view is definitely using it constantly as it is keeping the two-way binding in sync.

在 personInfo 对象中包含 btnValue 应该没有问题,因为这是一个 ViewModel 并且您实际上是根据该模型中的内容来驱动视图(按钮的值)。在将人员持久保存到数据存储时,您可能不会在稍后使用该值时使用它,但您的视图肯定会不断使用它,因为它保持双向绑定同步。

You should really be putting make_address_editable inside your personInfo model as well since I don't think you want to have a "global" flag for each individual person. Having make_address_editable directly on $scope will prevent you from tracking it on a person by person basis.

您真的应该将 make_address_editable 也放入您的 personInfo 模型中,因为我认为您不想为每个人设置一个“全局”标志。直接在 $scope 上使用 make_address_editable 将阻止您逐个跟踪它。

If you really must make a local variable, you can try this. See jsfiddleI made starting with your example:

如果你真的必须创建一个局部变量,你可以试试这个。请参阅我从您的示例开始制作的jsfiddle

angular.module('coolApp', [])
    .controller('PersonCtrl', function ($scope) {
        $scope.persons = [{'name': 'Alex', 'gender': 'Male', 'address': [{'placename': 'Home', 'address': '1234 Dr'},{'placename': 'Office', 'address': '12345 Dr'}]}, {'name': 'Alexis', 'gender': 'Female', 'address': [{'placename': 'Home', 'address': '12345 Dr'},{'placename': 'Office', 'address': '123456 Dr'}]}];

    //$scope.make_address_editable = false;
    //$scope.btnValue = 'Edit';
    $scope.changeBtnValue = function (viewModel) {
        if (viewModel.editable === true) {
            viewModel.btnValue = 'Save';
        } else {
            viewModel.btnValue = 'Edit';
        }
    };
});

Then use ng-init within your repeater to make a viewModel object that is local to the repeater scope. This will keep your persons from changing:

然后在你的转发器中使用 ng-init 来创建一个转发器范围本地的 viewModel 对象。这将防止你的人改变:

<div ng-app="coolApp">
    <div ng-controller="PersonCtrl">
        <table>
            <tr ng-repeat="personInfo in persons" ng-init="viewModel={btnValue: 'Edit', editable: false}">
                <td>{{personInfo.name}}</td>
                <td>{{personInfo.gender}}</td>
                <td>
                    <select ng-model="selected_address" ng-options="address.placename for address in personInfo.address"></select> <span ng-show="viewModel.editable===false;">{{selected_address.address}}</span>

                    <input type="text" style="width: 22em;" ng-show="viewModel.editable" ng-model="selected_address.address" />
                    <input style="margin-left: 2em;" type="button" value="{{viewModel.btnValue}}" ng-show="selected_address" ng-click="viewModel.editable=!viewModel.editable; changeBtnValue(viewModel);" />
                </td>
            </tr>
        </table>
    <br><br>
    {{persons}}
    </div>
</div>

回答by Kumar

btnValue is supposed to change for all "persons". But I think you'd want it to change for specific "person" objects only.

btnValue 应该为所有“人”而改变。但我认为您希望它仅针对特定的“人物”对象进行更改。

There is an ugly way to do this. Pass the event to the function.

有一种丑陋的方法可以做到这一点。将事件传递给函数。

ng-click="make_address_editable=!make_address_editable; changeBtnValue($event)"

Inside the changeBtnValue function, change the "value" attribute of the corresponding input tag.

在 changeBtnValue 函数中,更改相应输入标签的“value”属性。

$scope.changeBtnValue = function(event){
          var inputTag = event.target;
}

"inputTag" variable will hold HTML Element object representing the corresponding input tag. Change the "value" attribute of the tag to "save"/"edit" or anything else. THis method is ugly because you manipulate the View from within the JS code. People usually try to avoid this.

“inputTag”变量将保存表示相应输入标签的 HTML 元素对象。将标签的“值”属性更改为“保存”/“编辑”或其他任何内容。这个方法很难看,因为你在 JS 代码中操作了 View。人们通常会尽量避免这种情况。