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; });
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.
- ng-repeat : angularjs docs
- load JSON : #1 see this link, loading a json file #2 see this link, loading a json file
Answers 4
Few observations as per your code :
- 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)
. - Use
ui-router
instead ofngRoute
to get better asngRoute
is outdated. - Instead of redirecting a user to a html template (
/AngularTask/NewsViewer.html
) directly, change the state of the view usingui-sref
withparams
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.
0 comments:
Post a Comment