Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I have a JSON file which has an array of objects. 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.

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

I know the solution involves $http

I'm thinking maybe nest the $http-post method inside the $http-get method?

$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.

share|improve this question
1  
What about what you are doing is not working except for the fact that you are not passing data to $http.post and you look like you are trying to define a function instead of execute it? Did you read the documentation for $http.post? – Goblinlord 16 hours ago

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().

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

share|improve this answer

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. The blog requires rendering of HTML to be able to show in the front end as parsed html instead of showing it as text.

I could've used a filter in the html and just did something like <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.

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. 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. In the success promise, you see I have responseService.handleArticles. This will do the getting/trusting of html for me:

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. 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:

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.

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.

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:

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? It would not be ideal to handle all of that logic inside of your service http call. It would get very messy very quick. Instead, use the one line `$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).

                 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.

share|improve this answer

It's impossible to write to a file using client-side JavaScript. To do that, you need to use a server-side language such as PHP or Node.js

Since this is tagged JavaScript, node will be the solution I use

Specifically, we're looking for the fs module. 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. I need to make this clear.

share|improve this answer
    
I can't say its not odd they way you answered your own question. Considering you said you thought you would need to use "$http" it seems obvious you would be doing the modification on some server (using http obviously?). Either way, I must disagree with you that it is not possible to do this client-side. You can read files, process them, then output a file using createObjectUrl(). Here is a reference for looking into using local files: html5rocks.com/en/tutorials/file/dndfiles – Goblinlord 10 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.