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

2
  • 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? Commented Feb 1, 2015 at 15:31
  • Ah sorry that is a typo mistake, I'll fix it right away Commented Feb 1, 2015 at 15:44

4 Answers 4

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)

Sign up to request clarification or add additional context in comments.

11 Comments

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?
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 ?
I did change to scope for singleStory but it seems it still doesnt render the data.
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?
It shows the response data that I wanted, but its weird that it doesnt render
|
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.

2 Comments

Why do you say that this and scope are not the same thing? Whate are the major difference?
Hey . There is a pretty good explanation here stackoverflow.com/questions/11605917/…
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>

1 Comment

Tried it, but it doesn't render anything.
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:

2 Comments

Are you sure that is the problem? but why on other tutorials that I have come up across don't have this 'ngSanitize' module?
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.