简体   繁体   English

AngularJS-使用$ http更新数组内的嵌套对象属性

[英]AngularJS - Update nested object property inside array using $http

I have a JSON file which has an array of objects. 我有一个包含对象数组的JSON文件。 Like this 像这样

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

On the click of a button, I need to update this file. 单击一个按钮,我需要更新此文件。 I need to change the name attribute inside the properties attribute of the first object inside the array. 我需要更改数组内第一个对象的properties属性内的name属性。

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

I know the solution involves $http 我知道解决方案涉及$http

I'm thinking maybe nest the $http-post method inside the $http-get method? 我在想也许$ 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';
                });
            }
        });

Good luck! 祝好运! This is a tough one. 这是困难的一个。

You should probably be taking a function argument. 您可能应该接受一个函数参数。 Also, why are you trying to modify it after a post (presumably the post updates the server). 另外,为什么要在发布后尝试修改它(大概是发布会更新服务器)。 Retrieve, modify, then post back to the server. 检索,修改,然后回发到服务器。 Also you should send the data using an argument with $http.post(). 另外,您还应该使用$ http.post()参数来发送数据。

angular $http docs 角$ http文档

 $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); }) } 

I think what you are doing will be a common task, and you would want to make your life easier by not having large amount of code in one function/file, as well as being able to find and maintain it more easily. 我认为您正在做的事情将是一项常见的任务,并且您希望通过在一个函数/文件中没有大量代码以及能够更轻松地查找和维护它来使您的生活更轻松。

I built an API for a blog and used AngularJS for the front end. 我为博客构建了一个API,并在前端使用了AngularJS。 The blog requires rendering of HTML to be able to show in the front end as parsed html instead of showing it as text. 该博客要求呈现HTML,以便在前端显示为已解析的html,而不是显示为文本。

I could've used a filter in the html and just did something like <h1 ng-bind-html="article | rawHtml"></h1> . 我本可以在html中使用过滤器,并且只做了<h1 ng-bind-html="article | rawHtml"></h1> Problem solved and only requires a simple filter. 问题已解决,只需要一个简单的过滤器。 But I did not do this because I think it is much better to have the HTML already trusted before it even gets to the HTML. 但是我没有这样做,因为我认为在HTML甚至不包含HTML之前就已经值得信任了会更好。

This leads me to the answer to your question by following a similar solution I used to do the getting/trusting of HTML in a filter before it reaches the HTML. 通过遵循一种我曾经在过滤器到达HTML之前对HTML进行获取/信任的类似解决方案,这使我找到了您的问题的答案。 This is how you could also handle the logic of updating your object . 这也是您如何处理更新对象的逻辑

Try something along these lines: 尝试以下方法:

In article.service.js , I have a function that will get one article. article.service.js中 ,我有一个将获得一篇文章的函数。 In the success promise, you see I have responseService.handleArticles . 在成功承诺中,您会看到我具有responseService.handleArticles This will do the getting/trusting of html for me: 这将为我完成html的获取/信任工作:

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

In response.service.js , I have a function that will handle logic for successfully getting an article, or in your case whatever object you want. response.service.js中 ,我有一个函数可以处理成功获取文章或您想要的任何对象的逻辑。 It also makes the call to do the "transformation", or "updating" or the object: 它还调用执行“转换”或“更新”或对象:

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

    handleError(res);
}

You see how I use a filter on my articles and then return? 您了解我如何在文章上使用过滤器然后返回吗? Let's take a look inside my filter. 让我们看看我的过滤器内部。

articles.filter.js: article.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);
}

As you can see in my articles filter above, I take in either a single article or multiple articles, and then handle logic on them (using other functions/filters) to get the HTML from the response and trust it so that I can use it in ng-bind-html in the html without having to pipe it to my filter. 如您在上面的articles过滤器中所看到的,我会收录一篇文章或多篇文章,然后处理它们上的逻辑(使用其他函数/过滤器)以从响应中获取HTML并信任它,以便我可以使用它在ng-bind-html中的ng-bind-html中,而不必将其通过管道传递到我的过滤器中。

This is where you would want to add your logic to update a certain property. 这是您要添加逻辑以更新特定属性的地方。

For example, you could have a filter called update and what it would do it take a set of data similar to my articles filter, and do something to it, and then return that data back. 例如,您可能有一个名为update的过滤器,它将执行类似于我的文章过滤器的一组数据,然后对其进行处理,然后将其返回。

For your case: 对于您的情况:

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

In the update filter you could have something like this: update过滤器中,您可能会遇到以下内容:

function update($) {
    return filter;

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

        return response;
    }
}

This will be very helpful later on when you are updating more than just one property name. 以后在更新多个属性名称时,这将非常有帮助。 What if you have 15 properties that need some kind of data manipulation? 如果您有15个需要某种数据处理的属性,该怎么办? It would not be ideal to handle all of that logic inside of your service http call. 在服务http调用中处理所有这些逻辑不是理想的。 It would get very messy very quick. 它很快就会变得非常混乱。 Instead, use the one line `$filter('update')(response); 相反,使用一行$ filter('update')(response); and handle that logic elsewhere. 并在其他地方处理该逻辑。

Not only is this approach better looking because of having separation of concerns and smaller functions, it is more maintainable because you can now create areas to 1. get data (your service), 2. transform the data (your filters), 3. bind the data to your views (your controller). 这种方法不仅具有更好的关注点和较小的功能,而且看起来更易于维护,因为您现在可以创建以下区域:1.获取数据(您的服务),2.转换数据(您的过滤器),3.绑定数据到您的视图(您的控制器)。

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

This is just my approach and it is by no means the "best", but it works for me and I think it may help you too. 这只是我的方法,绝不是“最好的”方法,但是它对我有用,我认为它也可能对您有所帮助。

It's impossible to write to a file using client-side JavaScript. 使用客户端JavaScript写入文件是不可能的。 To do that, you need to use a server-side language such as PHP or Node.js 为此,您需要使用服务器端语言,例如PHP或Node.js。

Since this is tagged JavaScript, node will be the solution I use 由于这是标记为JavaScript的,因此节点将是我使用的解决方案

Specifically, we're looking for the fs module. 具体来说,我们正在寻找fs模块。 Something like this might work 这样的事情可能会起作用

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));
        }

    });

For nested objects, you would use one extra pair of brackets. 对于嵌套对象,您将使用一对额外的括号。

But this is not possible with client side JavaScript. 但这对于客户端JavaScript是不可能的。 I need to make this clear. 我需要说清楚。

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

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