2

Currently I'm trying to render a specific data on angular with node/express as the backend.

What I'm trying to achieve is whenever a user clicks a specific story, it will link to that specific story page that belongs to a user who created the story.

api.js

apiRouter.get('/:user_name/:story_id', function(req, res) {

            User.findOne({ name: req.params.user_name }, function(err, user, next) {

                if(err) return next(err);

                Story.findById(req.params.story_id, function(err, story) {

                    if(err) {
                        res.send(err);
                        return;
                    }

                    res.json({
                        name: user.name,
                        story_id: story._id,
                        content: story.content

                    });
                });
            });
        });

As for the backend(api) It does show the specific data that I wanted with POSTMAN chrome tool but when it comes to angular I'm really confuse of how to render the data to the html.

service.js

storyFactory.getSingleStory = function(user_name, story_id) {
        return $http.get('/api/' + user_name + story_id);
    }

controller.js

angular.module('storyCtrl', ['storyService'])

.controller('StoryController', function(Story, $routeParams) {

    var vm = this;


    Story.getSingleStory($routeParams.user_name, $routeParams.story_id)
        .success(function(data) {
            vm.storyData = data;
        });

});

app.routes.js

.when('/:user_name/:story_id', {
            templateUrl: 'app/views/pages/users/single.html',
            controller: 'StoryController',
            controllerAs: 'story'
        })

index.html ( Just going to show the line where it goes to the single.html )

<a href="/{{ main.user.name }}/{{ each._id }}"><h4>{{ each.content }}</h4>

single.html

Hello {{ main.user.name }}

<p>{{ story.content }}</p>

So far I couldn't manage to render the data properly with angular while with node/express I could query the data that I wanted with POSTMAN. I'm clueless and please save me from this confusion that angular giving me :)

airsoftFreak
  • 1,450
  • 5
  • 34
  • 64
  • In method getSingleStory of your service, why are your calling post method $http.post('/api/' + user_name + story_id); instead of $http.get('/api/' + user_name +'/' story_id); Is that a typo mistake? – Shripal Soni Feb 01 '15 at 15:31
  • Ah sorry that is a typo mistake, I'll fix it right away – airsoftFreak Feb 01 '15 at 15:44

4 Answers4

1

I have went through your code, and you can improve in following parts:

  1. Instead of using var vm = this in your controller, you should bind all objects to $scope, which is the key to two-way data binding. For instance

    angular.module('storyCtrl', ['storyService'])
    .controller('StoryController', function($scope, Story, $routeParams) {
      var vm = this;
      Story.all().success(function(data) {
        $scope.stories = data;
      });
    

    Then stories can be accessed in View directly. It would be more readable than controllerName.stories in HTML.

    <div class="col-md-6" ng-controller="StoryController as story">
      <div class="panel-body" ng-repeat="story in stories">
        <div class="comment-text">
          <a href="/{{ main.user.name }}/{{ story._id }}"><h4>{{ story.content }}</h4></a>
        </div>
      </div>
    </div>
    
  2. Keep in mind, then(function(response)) will only pass one parameter to the chained function while .success(function(data, status, headers, config)) will retrieve data from HTTP response. Then your code to load single story can be converted to

    Story.getSingleStory($routeParams.user_name, $routeParams.story_id)
    .then(function(data, status, headers, config) {
        $scope.storyData = data;
    });
    

    Now we can access storyData in View.

  3. There is a tiny bug in your Story Service. Change generateReq('GET', '/api/' + user_name + story_id) to generateReq('GET', '/api/' + user_name + '/' + story_id)

Rebornix
  • 5,272
  • 1
  • 23
  • 26
  • Thank you for you help again, I'm just wondering that angularjs is going to drop $scope in 2.0 version, and that's the reason why I've been using **this** instead of $scope. Any thoughts on that? – airsoftFreak Feb 02 '15 at 09:27
  • I will change all of my codes to $scope if its better. and If you go to the web app, whenever I login, I need to refresh the page in order to see the username. Is it because of **this** ? – airsoftFreak Feb 02 '15 at 09:30
  • I did change to scope for singleStory but it seems it still doesnt render the data. – airsoftFreak Feb 02 '15 at 09:46
  • Try to move the 'url redirect' code into the 'then' phase of Auth.getUser(). It might solve the username problem. For data rendering, what's the response data of getting single story you saw in debugging tool? – Rebornix Feb 02 '15 at 10:08
  • It shows the response data that I wanted, but its weird that it doesnt render – airsoftFreak Feb 02 '15 at 10:09
  • Push the newest code to github and deploy to heroku. Let me have a look when I'm home. – Rebornix Feb 02 '15 at 10:11
  • @airsoftFreak check this [link](https://user-testing2015.herokuapp.com/rebornix/54cf30babc2045030032e6a7) the data binding already worked now. You only need to change `then` to `success` in `StoryController`. – Rebornix Feb 02 '15 at 12:09
  • I find the `username doesn't get updated` problem is caused by '$location.path('/');', you'd better use `$state.go()` to navigate state instead of redirecting to urls. You can spend some time reading [Angular related articles, videos](https://github.com/jmcunningham/AngularJS-Learning) to get a brief understanding of how Angular works. It can help decrease bug numbers and speed up your development. – Rebornix Feb 02 '15 at 12:22
  • You have save me again! Thank you so much. I believe I need to spend sometime reading about the link that you gave me. I will post more questions in the future, and I will invite you for sure. Any awesome angular book that you recommend me to read(I mean the angular book that I need)? again THANK YOU! – airsoftFreak Feb 02 '15 at 13:09
  • and for the username, are you sure there's no way I could solve it using $location.path()? – airsoftFreak Feb 02 '15 at 13:13
  • Personally I suggest http://www.syncfusion.com/resources/techportal/ebooks/angularjs it's free and for beginners. The username problem, I'm not sure what the root cause is and it's beyond my knowledge. I'll ping you if I have better ideas. – Rebornix Feb 02 '15 at 13:20
0

Your problem may be due to the fact that you story data is html and is therefore untrusted by default. For security reasons Angular will not allow you to render html directly into the page, instead you must explicitly tell Angular to trust the html content

To do this you must first include the ngSanitize module in your app.

angular.module('app', ['ngSanitize']);

You can then inject the $sce service which allows you to trust the html content. The code below has a data item with a property called Html that contains raw html text returned from an api. I just overwrite this raw html text with the $sce trust object returned from the $sce.trustAsHtml() method.

item.Html = $sce.trustAsHtml(item.Html);

Once you have trusted your html, you are now free to render it using the ng-bind-html attribute.

<div ng-bind-html="item.Html"></div>

For more information and further examples see:

Community
  • 1
  • 1
biofractal
  • 18,963
  • 12
  • 70
  • 116
  • Are you sure that is the problem? but why on other tutorials that I have come up across don't have this 'ngSanitize' module? – airsoftFreak Feb 02 '15 at 01:15
  • Maybe I misread, I can see from the other suggestions that you are struggling to get your data on $scope so you can render it in the view. When you do manage that, come back here so you can see how to render the actual html as opposed to just printing the raw string. Sorry for the confusion. – biofractal Feb 02 '15 at 10:33
0

If you want to set values on the controller and see them in the html view. Set the view model on the controller's scope rather than using this. This and scope are not always the same thing and for binding I believe you need scope.

Noel
  • 567
  • 1
  • 4
  • 11
  • Why do you say that **this** and **scope** are not the same thing? Whate are the major difference? – airsoftFreak Feb 02 '15 at 01:16
  • Hey . There is a pretty good explanation here http://stackoverflow.com/questions/11605917/this-vs-scope-in-angularjs-controllers – Noel Feb 02 '15 at 02:52
0

these expressions

// file: single.html
{{ main.user.name }}
<p>{{ story.content }}</p>

don't seem to be bound to any variable in 'StoryController'

Try using

// file: single.html
{{ story.storyData.user.name }}
<p>{{ story.storyData.content }}</p>
Michael Coleman
  • 3,288
  • 3
  • 19
  • 18