Reputation: 937
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.
Upvotes: 7
Views: 2570
Reputation: 6546
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.
Upvotes: -1
Reputation: 27222
Few observations as per your code :
<a data-ng-href="/AngularTask/NewsViewer.html">more</a>
will break the pupose of AngularJS which is Single page application (SPA)
.ui-router
instead of ngRoute
to get better as ngRoute
is outdated./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
Upvotes: 2
Reputation: 63
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.
Upvotes: 3
Reputation: 23859
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.
Upvotes: 2
Reputation: 199
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>
Upvotes: -1
Reputation: 308
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
Upvotes: 2