AngularJS:在初始运行时之后使用控制器构造的JSON对象更新DOM

时间:2013-12-24 17:36:42

标签: javascript json angularjs

我认为我没有在“Angular Way”中做某些部分,因为我无法在文档的任何地方找到类似的用例。

我的输入采用逗号分隔的输入,并使用ng-submit(在weatherController中)调用此函数:

$scope.submit = function() {    

    var rawZipString = this.text;
    var strippedString = rawZipString.replace(/\s+/g, '');
    var zipArray = strippedString.split(',');

    for(i=0;i<zipArray.length;i++){
        Weather.getWeatherForecast(zipArray[i])
        .then(function(forecast){
            $scope.temperatures.push(forecast);
        })
    }

    /** Create weather objects */
    for(i=0;i<$scope.temperatures.length;i++){
            var tempForecast = new weatherConstructor(zipArray[i],$scope.temperatures[i]);
            $scope.zipForecast.push(tempForecast);
        }

    /** Format as JSON */
    $scope.DOMdata = angular.toJson($scope.zipForecast);
        console.log($scope.DOMdata);    
    }

这是weatherConstructor:

function weatherConstructor(zip,temp){
    this.zip = zip;
    this.temp = temp;
}

我不确定如何获取构造的JSON对象($ scope.DOMdata)并将其推送到视图,如下所示:

<div ng-controller="weatherController">
<h4 ng-repeat="DOM in DOMdata">
    {{DOM.zip}} now is {{DOM.temp}}
</h4>   

2 个答案:

答案 0 :(得分:1)

HTML:您需要将ng-modelng-list一起使用,以自动将逗号分隔值转换为数组。

<input type="text" ng-model="text" ng-list>
<div ng-controller="weatherController">
<h4 ng-repeat="DOM in DOMdata">
  {{DOM.zip}} now is {{DOM.temp}}
</h4>

JS:你需要在这里注入$q服务。

$scope.submit = function () {
  var zipArray = this.text;
  var all = [];
  for (i = 0; i < zipArray.length; i++) {
    var got = Weather.getWeatherForecast(zipArray[i])
      .then(function (forecast) {
        return forecast;
      })
    all.push(got);
  }

  // You have to wait until all temperatures are completed
  $q.all(all).then(function(forecasts) {

    // You have to assign temperature in here,
    // as forecasts may arrive at a different time
    // if you want to relay on the order of temperatures to match zipArray
    $scope.temperatures = forecasts;

    $scope.zipForecast = [];

    for (i = 0; i < $scope.temperatures.length; i++) {
      var tempForecast = new weatherConstructor(zipArray[i], $scope.temperatures[i]);
      $scope.zipForecast.push(tempForecast);
    }

    // you don't need toJson here, it is already a object
    $scope.DOMdata = $scope.zipForecast;
    console.log($scope.DOMdata);
  });
}


function weatherConstructor(zip,temp){
  this.zip = zip;
  this.temp = temp;
}

答案 1 :(得分:0)

我想回答一下你的问题,关于这段代码不符合“Angular Way”的问题,我还想建议你也尽可能地编写最简单的代码。实际上,我认为Angular最好的事情之一是它允许我们使用非常简单的javascript代码(大多数!)进行非常强大的DOM操作。

您误以为将“数据”“发送”到DOM。在Angular JS控制器中,$ scope的每个属性都自动绑定到UI。这意味着您可以通过DOM更改$ scope属性的值(例如,通过更改输入的值),并在控制器中以编程方式更改值(并且该更改将立即反映在任何表示形式中DOM中的那个属性。

因此,对于您的问题,我认为最好的方法是从最终目标入手。我将在这里提出一个建议:让我们直接使用$ scope.temperatures而不是将其重命名为DOMdata。它具有更多的语义价值!

<h4 ng-repeat='item in temperatures'>
    {{item.zip}} now is {{item.temp}}
</h4>

现在在控制器中,如果我们希望我们的数据看起来像这样,我们可以简化提交逻辑:

[{zip: 30224, temp: 30}, {zip: 90210, temp: 33}, {zip: 30695, temp: 28}]

然后控制器可能看起来像这样:

weatherController = ['$scope', Weather,
    function($scope, Weather) {
        $scope.temperatures = [];
        $scope.text = '';

        $scope.submit = function() {
            this.temperatures = []; // clear it out
            var zipArray = this.text.replace(/s+/g, '').split(',');
            for(var i = 0; i < zipArray.length; i++) {
                Weather.getWeatherForecast(zipArray[i]).
                then(function(forecast) {
                    $scope.temperatures.push({zip: zipArray[i], temp: forecast});
                });
            }
         };
     }
];

那应该是它。现在,正如另一个答案所指出的,过滤器有利于改变显示值,同时保持底层数据的完整性。所以:

{{item.zip}} now is {{item.temp | degrees}}.