Saturday, November 18, 2017

How to show a dynamic content in the same page using Angularjs 1.6?

Leave a Comment

I'm a newbie to Angular. I need to render a dynamic content from JSON file using AngularJS 1.6. Here is what I have.

News.json

   {   "Articles": [     {       "Title": "News 1",           "Abstract": "News 1 abstract ...",       "Body": "News 1 starts here.... ",       "Comments": [         {           "comment 1" : "Comment 1 goes here",           "comment 2" : "Comment 2 goes here",           "comment 3" : "Comment 3 goes here"         }]     },      {       "Title": "News 2",       "Abstract": "News 2 abstract ... ",       "Body": "News 2 starts here...",       "Comments": [         {           "comment 1" : "Comment 1 goes here",           "comment 2" : "Comment 2 goes here"         }]     }       ] } 

Script.js

app.config(function ($routeProvider) {     $routeProvider         .when("/News", {             templateUrl: "NewsViewer.html",             controller: "showNews"         }); });  app.controller("showNews", ["$scope", "$http", function ($scope, $http) {     $http({         method: 'GET',         url: 'News/News.json'     }).then(function success(data) {         $scope.News = data.data;     }); }]); 

News.html

<div class="container-fluid">      <div class="row">          <div class="col-md-offset-1 col-md-6">             <div ng-controller="NewsRendering">                 <div ng-repeat="NewsData in News.Articles">                     <h3>{{NewsData.Title}}</h3>                     <p>{{NewsData.Abstract}}</p>                     <a data-ng-href="/AngularTask/NewsViewer.html">more</a>                 </div>             </div>         </div>          <div class="col-md-4 questionnaire">             <h3>Questionnaire of the day</h3>         </div>      </div>  </div> 

NewsViewer.html

<div class="container-fluid">     <div class="row">         <div class="col-md-offset-1 col-md-6">             <div ng-controller="showNews">                 <div>                     <h3>{{News.Articles[0].Title}}</h3>                     <p>{{News.Articles[0].Abstract}}</p>                     <p>{{News.Articles[0].Body}}</p>                 </div>                  <div class="comments">                     <h4>Comments</h4>                     <hr>                     <p>{{News.Articles[0].Comments[0]}}</p>                 </div>             </div>         </div>     </div> </div> 

This code is working fine, but this code is not dynamic. My problem how to make it dynamic and can show whatever in json file. What should I do in JS code to pass the index of the array of the JSON File.

As you can see <h3>{{News.Articles[0].Title}}</h3> is showing only the first Title of the JSON file. I need to write it to be <h3>{{News.Articles[index of whatever].Title}}</h3>

Note: News.json has around 100,000 records. I make it two, just to show the code and describe the problem.

6 Answers

Answers 1

You need to use a routing service in combination with the rootScope to save the selected object. I made an easy example for you:

angular .module('myApp', ['ngRoute']) .config(['$routeProvider', function($routeProvider){     $routeProvider         .when('/list', {             templateUrl: 'pages/list.html',             controller: 'listController'         })         .when('/details', {             templateUrl : 'pages/details.html',             controller: 'displayController'         })         .otherwise({redirectTo: '/list'}); }]) .controller('listController', function($scope, $rootScope) {     var myObject = {         Listoflinks: [{             "Title": "Link 1",             "Abstract": "abstract is here ....",             "Body": "Body is here ...",         },         {             "Title": "Link 1",             "Abstract": "abstract is here ....",             "Body": "Body is here ...",         }]     }     $rootScope.detail = myObject.Listoflinks[0]; }) .controller('displayController', function($scope, $rootScope) {     $scope.detail = $rootScope.detail; }); 

https://plnkr.co/edit/0SYnFcjlgGyTowlcpvgz?p=catalogue

Answers 2

You can do it by passing the index of the news to the /News route.

First, change News.html so it tracks the data by index, and then appends the index of the item to the ng-href.

<div ng-repeat="NewsData in News.Articles track by $index">   <h3>{{NewsData.Title}}</h3>   <p>{{NewsData.Abstract}}</p>   <a data-ng-href="/AngularTask/NewsViewer.html?index={{$index}}">more</a> </div> 

Now, for each visit, you will see a new query parameter in the NewsViewer route, which will be index.

Second, change the controller, so it takes the advantage of passed index using $routeParams.

app.controller("showNews", ["$scope", "$http", "$routeParams",   function ($scope, $http, $routeParams) {     $http({         method: 'GET',         url: 'News/News.json'     }).then(function success(data) {         $scope.News = data.data.Articles[$routeParams.index];     }); }]); 

This way, $scope.News will contain the article which resides on the passed index.

Finally, change NewsViewer.html so that it uses $scope.News.

<div class="container-fluid">     <div class="row">         <div class="col-md-offset-1 col-md-6">             <div ng-controller="showNews">                 <div>                     <h3>{{News.Title}}</h3>                     <p>{{News.Abstract}}</p>                     <p>{{News.Body}}</p>                 </div>                  <div class="comments">                     <h4>Comments</h4>                     <hr>                     <p>{{News.Comments[0]}}</p>                 </div>             </div>         </div>     </div> </div> 

For comments, you can again use ng-repeat directive to show all the comments, iterating over them one-by-one.

Hope this answers your question.

Answers 3

I think what you need is using 'ng-repeat' to show the Array Articles and '$http.get()' to load the json.file "dynamically" as you want.

Answers 4

Few observations as per your code :

  1. This line of code <a data-ng-href="/AngularTask/NewsViewer.html">more</a> will break the pupose of AngularJS which is Single page application (SPA).
  2. Use ui-router instead of ngRoute to get better as ngRoute is outdated.
  3. Instead of redirecting a user to a html template (/AngularTask/NewsViewer.html) directly, change the state of the view using ui-sref with params and pass the $index as param value.

Try below approach to get result as per the expectation :

News.html

  <div ng-repeat="NewsData in News.Articles">     <h3>{{NewsData.Title}}</h3>     <p>{{NewsData.Abstract}}</p>     <a href="javascript:void(0)" ui-sref="newsdetails({index: $index})">more</a>   </div> 

routes.js :

$stateProvider     .state('newsdetails', {       url: '/news-details/:index',       controller: 'showNews',       templateUrl: 'NewsViewer.html'     })     .... 

Controller :

.controller('showNews', function($scope, $stateParams) {     $scope.indexVal = $stateParams.index; // getting index value passed from news.html }); 

NewsViewer.html :

 <div ng-controller="showNews">      <div>          <h3>{{News.Articles[indexVal].Title}}</h3>          <p>{{News.Articles[indexVal].Abstract}}</p>          <p>{{News.Articles[indexVal].Body}}</p>      </div>  </div> 

Working demo : https://plnkr.co/edit/jfzm00ksZMAC8sGGUZSR?p=preview

Answers 5

I think this is what you want

NewsViewer.html

        <div class="container-fluid">     <div class="row">         <div class="col-md-offset-1 col-md-6">             <div ng-controller="showNews">                 <div>                     <div>                         <h3>{{selectedArticle.Title}}</h3>                         <p>{{selectedArticle.Abstract}}</p>                         <p>{{selectedArticle.Body}}</p>                     </div>                      <div class="comments">                         <h4>Comments</h4>                         <hr>                         <div ng-repeat="comment in selectedArticle.Comments">                             <p ng-repeat="(key, value) in comment">                                 <strong>{{key}}</strong>: {{value}}                             </p>                         </div>                     </div>                 </div>             </div>         </div>     </div> </div> 

Answers 6

Please find the working solution below

https://embed.plnkr.co/rbNAcVGtBvTjl9VhfFAl/

Let me know, if you need further info. Enjoy :)

Edited

First of all we need to define two separate routes, one for News and one for Article

$routeProvider.when("/News", {     templateUrl: "News.html",     controller: "NewsContoller" }).when("/NewsViewer", {     templateUrl: "NewsViewer.html",     controller: "NewsViewerController" }) 

As you see, there are two separate controllers handling each route.

Then we need a value service to pass data between routes

angular.module('app').value('viewData', {}) 

After that on click of more link, set the value of viewData to that specific article and redirect to /NewsViewer route. And, on NewsViewerController retrieve that value from viewData and pass it to $scope.

Template: News.html

<div>   <div ng-repeat="NewsData in News.Articles">     <h3>{{NewsData.Title}}</h3>     <p>{{NewsData.Abstract}}</p>     <a href ng-click="showArticle(NewsData)">more</a>   </div> </div> 

Template: NewsViewer.html

<div>   <div>     <h3>{{Article.Title}}</h3>     <p>{{Article.Abstract}}</p>     <p>{{Article.Body}}</p>   </div>    <div class="comments">     <h4>Comments</h4>     <hr>     <p ng-repeat="(key, value) in Article.Comments[0]">       {{value}}     </p>   </div> </div> <a ng-href="#!/News">All News</a> 

Controller: NewsController

angular.module('app').controller('NewsContoller', function($scope, $http, viewData, $location) {   $http({     method: 'GET',     url: 'News.json'   }).then(function success(response) {     $scope.News = response.data;   });   $scope.showArticle = function(article) {     viewData.article = article;     $location.path("/NewsViewer");   } }) 

Controller: NewsViewerController

angular.module('app').controller('NewsViewerController', function($scope, viewData) {   $scope.Article = viewData.article; }) 

Link of plunker is above in original answer.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment