【问题标题】:AngularJS - Update nested object property inside array using $httpAngularJS - 使用 $http 更新数组内的嵌套对象属性
【发布时间】:2016-02-16 00:38:57
【问题描述】:

我有一个包含对象数组的 JSON 文件。像这样

[
    { "id": 1, "properties": { "name": "Sam", "color": "blue" } },
    { "id": 2, "properties": { "name": "George", "color": "green" } }
];

点击一个按钮,我需要更新这个文件。我需要更改数组中第一个对象的 properties 属性中的 name 属性。

<button ng-click="updateProperties()">Update Names</button>

我知道解决方案涉及$http

我在想也许将 $http-post 方法嵌套在 $http-get 方法中?

$scope.updateProperties = function() {
    $http.get('data.json')
        .then(function(response) {
            var name = response.data[0].properties.name;
            $http.post('data.json') {
                .then(function(response) {
                    response.data[0].properties.name = 'Lucas';
                });
            }
        });

祝你好运!这是一个艰难的过程。

【问题讨论】:

  • 除了您没有将数据传递给 $http.post 并且您看起来像是在尝试定义一个函数而不是执行它之外,您正在做的事情怎么办?您是否阅读过 $http.post 的文档?

标签: javascript arrays angularjs ajax object


【解决方案1】:

您可能应该使用函数参数。另外,您为什么要在发布后尝试修改它(大概是帖子更新了服务器)。检索、修改,然后发回服务器。此外,您应该使用带有 $http.post() 的参数发送数据。

angular $http docs

$scope.updateProperties = function() { // Update what with what???  Use one or more arguments?
  return $http.get('data.json')  // You could take the URL as argument
    .then(function(response) {
      response.data[0].properties.name = 'Lucas'; // Maybe use a function argument instead?
      return $http.post('data.json', response.data);
    })
}

【讨论】:

    【解决方案2】:

    我认为您正在做的事情将是一项常见的任务,并且您希望通过在一个函数/文件中不包含大量代码以及能够更轻松地找到和维护它来使您的生活更轻松。

    我为博客构建了一个 API,并将 AngularJS 用于前端。博客需要渲染 HTML 才能在前端显示为解析后的 html,而不是显示为文本。

    我本可以在 html 中使用过滤器,然后执行&lt;h1 ng-bind-html="article | rawHtml"&gt;&lt;/h1&gt; 之类的操作。问题解决了,只需要一个简单的过滤器。但是我没有这样做,因为我认为最好在 HTML 到达 HTML 之前就已经信任它。

    这通过遵循我曾经在过滤器中获取/信任 HTML 到达 HTML 之前的类似解决方案,从而引导我回答您的问题。 这也是您处理对象更新逻辑的方式

    尝试以下方法:

    article.service.js 中,我有一个函数可以获取一篇文章。在成功的承诺中,你看我有responseService.handleArticles。这将为我完成 html 的获取/信任:

    function getOne(slug) {
        return $http.get(config.url + "/articles/" + slug)
            .then(responseService.handleArticles, responseService.handleError);
    }
    

    response.service.js 中,我有一个函数可以处理成功获取文章的逻辑,或者在您的情况下,可以处理您想要的任何对象。它还调用执行“转换”或“更新”或对象:

    function handleArticles(res) {
        if (typeof res.data === 'object')
            return $filter('articles')(res.data); // LOOK HERE
    
        handleError(res);
    }
    

    您看到我是如何对我的文章使用过滤器然后返回的吗?让我们看看我的过滤器内部。

    articles.filter.js:

    function articles($filter) {
        return filter;
    
        function filter(data) {
            if (data.hasOwnProperty('article'))
                beautifyHtml(data.article, $filter);
            else if (data.hasOwnProperty('articles'))
                for (var i = 0; i < data.articles.length; i++)
                    beautifyHtml(data.articles[i], $filter);
    
            return data;
        }
    }
    
    function beautifyHtml(article, $filter) {
        var trustedTitle = $filter('getTrustedHtml')(article.title);
        var trustedBody = $filter('getTrustedHtml')(article.body);
    
        article.title = $filter('renderHtml')(trustedTitle);
        article.body = $filter('renderHtml')(trustedBody);
    }
    

    正如您在上面的articles 过滤器中看到的那样,我接收一篇文章或多篇文章,然后处理它们的逻辑(使用其他函数/过滤器)以从响应中获取 HTML 并信任它我可以在 html 中的 ng-bind-html 中使用它,而无需将其通过管道传输到我的过滤器。

    这是您想要添加逻辑以更新某个属性的地方。

    例如,您可以有一个名为 update 的过滤器,它会采用类似于我的文章过滤器的一组数据,对其进行处理,然后返回该数据。

    对于您的情况:

    $scope.updateProperties = function() {
        $http.get('data.json')
            .then(function(response) {
                $http.post('data.json') {
                    .then(function(response) {
                        $filter('update')(response);
                    });
                }
            });
    

    update 过滤器中,您可以有这样的东西:

    function update($) {
        return filter;
    
        function filter(response) {
            response.data[0].properties.name = 'Lucas';
    
            return response;
        }
    }
    

    当您更新多个属性名称时,这将非常有用。如果您有 15 个属性需要某种数据操作怎么办?在服务 http 调用中处理所有这些逻辑并不理想。它会很快变得非常混乱。相反,使用一行 `$filter('update')(response);并在其他地方处理该逻辑。

    这种方法不仅因为关注点分离和功能更小而看起来更好看,而且更易于维护,因为您现在可以创建区域来 1. 获取数据(您的服务),2. 转换数据(您的过滤器), 3. 将数据绑定到您的视图(您的控制器)。

                     Service gets data
                             |
                             |
                   Filter manipulates data
                             |
                             |
              Service returns manipulated data
                             |
                             |
         Controller gets returned data from service
                             |
                             |
                 Happy HTML and happy coder
    

    这只是我的方法,它绝不是“最好的”,但它对我有用,我认为它也可以帮助你。

    【讨论】:

      【解决方案3】:

      使用客户端 JavaScript 写入文件是不可能的。为此,您需要使用 PHP 或 Node.js 等服务器端语言

      由于这是标记为 JavaScript,节点将是我使用的解决方案

      具体来说,我们正在寻找fs 模块。像这样的东西可能会起作用

      fs.readFile(USERS_FILE, function(err, data) {
          var data = JSON.parse(data);
      
          var named = data.filter(function(d) {
              return d["name"] != "";
          });
      
          var unNamed = data.filter(function(d) {
              return d["name"] == "";
          });
      
              named[0]["name"] = "Henry";
              if (data.length === named.length) {
                  fs.writeFile(FILE, JSON.stringify(named));
              }
              else {
                  allFiles = named.concat(unNamed);
                  fs.writeFile(FILE, JSON.stringify(allFiles));
              }
      
          });
      

      对于嵌套对象,您将使用一对额外的括号。

      但这对于客户端 JavaScript 是不可能的。我需要说清楚。

      【讨论】:

      • 我不能说他们回答自己问题的方式并不奇怪。考虑到您说您认为您需要使用“$http”,显然您将在某些服务器上进行修改(显然使用 http?)。无论哪种方式,我都必须不同意您的观点,即不可能在客户端进行此操作。您可以读取文件、处理它们,然后使用 createObjectUrl() 输出文件。这是查看使用本地文件的参考:html5rocks.com/en/tutorials/file/dndfiles
      猜你喜欢
      • 2016-07-27
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 2021-02-28
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多