Princeton Collins
Princeton Collins

Reputation: 65

ng-repeat not updating after db array update

I'm trying to get my ng-repeat to update after I create a new item in my Mongo DB. From what I've researched, this should happen automatically. I know that for every view a new $scope is made for that view, and to share data between all of your $scopes, you would use a service, which I beleive is what I'm doing... but maybe not.

Any help is appreciated, here is my code:

newblog.html

<div class="newblog">
<a ui-sref="blogs"><i class="fa fa-close fa-2x exit"></i></a>
<div class="form">
      <form>
            <i class="fa fa-pencil-square-o fa-5x"></i><br>

            <input class="blogtitle" type="text" ng-model="formData.title" placeholder="Blog Title" required /><br>

            <textarea ng-model="formData.body" rows="15" placeholder="Write the body of your blog here." required></textarea><br>

            <label for="">by:</label><br>
            <input class="blogauthor" type="text" ng-model="formData.author" placeholder="Author Name" required /><br><br>

            <button type="submit" ng-click="addPost()">Submit</button>  
      </form>
</div>

Here is the form for the new blog a user creates.

main.html

<div class="wrapper"> 
    <div class="blog-container" ng-repeat="data in blog | orderBy: '-pubdate'" ng-click="readPost(data._id)" ui-sref=".readblog">  
        <p><i class="fa fa-sticky-note"></i>&nbsp;<b>{{ data.title }}</b></p>
        <p>by {{ data.author }}</p> 
        <p>{{ data.pubdate | date }}</p>
        <br>
        <div>
            <p>{{ data.body }}</p>
        </div>
        <br><br>
    <div class="button-box">
        <div id="deletePost" ng-click="deletePost(data._id)"><i class="fa fa-trash-o fa-2x"></i></div>
    </div>
</div>

Here is the view with the ng-repeat.

Below is my controller and service.

mainCtrl.js

var app = angular.module("blog-app");

app.controller('MainController', ['mainService', '$scope', '$http', '$location', '$stateParams', '$state', function(mainService, $scope, $http, $location, $stateParams, $state) { 

$scope.formData = {};

$scope.blog = mainService.blog;

function getBlogs() {
  mainService.getPosts().then(function(data) {
    $scope.blog = data;
    console.log(data, "The blogs.");
  });
}

getBlogs();

$scope.addPost = function(data) {
      mainService.addPost($scope.formData).then(function(data) {
        $scope.formData = {};
        $location.path('blogs');
        $scope.blog.push(data);
        console.log(data, 'Blog created.');     
      }); 
        getBlogs();
  };

}]); //End Controller.

mainService.js

var app = angular.module("blog-app");

app.service('mainService', function($http, $q) {

    var blog = [];
    var readblog = {};
    var formData = {};

    this.getPosts = function() {
        return $http.get('/api/blogs').then(function(response){
            blog = response.data;
            return blog;
        });
    }

    this.readPost = function(id) {
        return $http.get('/api/blogs/' + id).then(function(response) {
            readblog = response.data;
            return readblog;
      });
    };

    this.addPost = function(formData) {
        return $http.post('/api/blogs', formData).then(function(response) {
            blog = response.data;
        })
    };

});

And my server.js...

    //Dependencies.
var express = require('express');
var router = express.Router();
// var sendgrid  = require('sendgrid')(process.env.U, process.env.PASSWORD)
var bodyParser = require('body-parser');
var cors = require('cors');
var mongoose = require('mongoose');
var mongojs = require('mongojs');
var http = require('http');
var path = require('path');
var fs = require('fs');
var dotenv = require('dotenv');

var port = 9001;
var mongoUri = 'mongodb://localhost:27017/blog-app';

var app = express();

app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());

//Blog Data & Data Storage.
//_________________________________________________________________________________________________________________________


var Schema = mongoose.Schema;

var blogSchema = new Schema({
    title : {type: String, min: 8, max: 50, required: true},
    body : {type: String, required: true},
    author : {type: String, min: 3, max: 40, required: true},
    pubdate : {type: Date, default: Date.now}
});

var Blog = mongoose.model('Blog', blogSchema);

//Routes.
//_________________________________________________________________________________________________________________________

// GET BLOGS!
app.get('/api/blogs', function(req, res) {
    Blog.find(function (err, blogs) {
        if (err)
            res.send(err);
        res.json(blogs);
    });
});

app.post('/api/blogs', function(req, res) {
    Blog.create({
        title: req.body.title,
        body: req.body.body,
        author: req.body.author,
        date: req.body.date
    }, function(err, blog) {
        if (err)
            res.send(err);
        Blog.find(function(err, blogs) {
            if (err)
                res.send(err);
            res.json(blogs);
        });
    });
});

mongoose.connect(mongoUri);
mongoose.connection.once('open', function() {
  console.log("Hey there! We are now connected to MongoDB at: ", mongoUri);
});

app.listen(port, function() {
  console.log('Magic! Listening on port: ', port);
});

I've been working on this going on two days, any help is much appreciated!

Upvotes: 2

Views: 133

Answers (3)

Princeton Collins
Princeton Collins

Reputation: 65

So, this might be a hacky way to do it but it performs exactly how I want it to. In my controller, in the addPost function, I added

$state.go('blogs).then(function() {
  $state.reload('blogs');
});

...so it looks like this...

$scope.addPost = function(newBlog) {
  mainService.addPost(newBlog).then(function(data) {
    $scope.blog = data;
    console.log(data, 'Blog created.');
    $state.go('blogs').then(function() {
      $state.reload('blogs');
    })
  }); 
};

I'm basically just going back to the scope where the ng-repeat is and then reloading it. It works great. But if there are any other alternatives, which I'm sure there are, I would love and greatly appreciate it if anyone would share theirs.

And would also appreciate it if anyone could enlighten me to possible bugs or future bugs this method might create. So far, I haven't seen any, but I'm still fairly green with AngularJS, so any ideas/comments are welcome.

Upvotes: 0

Shadi Shaaban
Shadi Shaaban

Reputation: 1720

In your addPost() handler, you either add the new post to the blog array via push() or reload the blogs by calling getBlogs(), any of these calls should be after the promise is completed.

First Approach: Using formData

  $scope.addPost = function(data) {
      mainService.addPost($scope.formData).then(function(data) {

        var newItem = jQuery.extend({}, $scope.formData); // copy the new inserted item from formData
        // newItem._id = data; // uncomment this to set the id
        $scope.blog.push(newItem); // this should be enough to update the repeater
        $scope.formData = {}; // clear formData
      }); 

  };

Second Approach: Reloading all the posts

  $scope.addPost = function(data) {
      mainService.addPost($scope.formData).then(function(data) {
        getBlogs();
        $scope.formData = {};
      }); 

  };

Upvotes: 0

floribon
floribon

Reputation: 19193

One issue could be that you are not waiting for a new post to be posted before retrieving the blogs.

try to move the getBlogs() call inside the callback of your addPost call:

$scope.addPost = function(data) {
  mainService.addPost($scope.formData).then(function(data) {
    $scope.formData = {};
    $location.path('blogs');
    $scope.blog.push(data);
    console.log(data, 'Blog created.');

    getBlogs();   
  }); 
};

Upvotes: 1

Related Questions