Generate Page Based on JSON Data - json

I'm using AngularJS for an app I'm building and was wondering if it's possible to generate pages when items are pushed to a JSON object called places. Each item when pushed is given a unique ID and I figured I could use this id (e.g. 123456) as part of the url like so site.com/places/123456.
{
"places" : [
{
"id" : 471756,
"title" : "The Whittington Hospital"
}
]
}
Is it possible to have this page generated automatically (for example, based on a template)?
I ask because I'm trying to build an app that let's users create their own hospitals via a form. Once a hospital is created and pushed to the JSON object, I'd like a page to be created for that hospital.
Can I use Angular for this? Any help is appreciated.
Thanks in advance!
UPDATE
Still having a bit of trouble with this. Here's what I've got so far.
place.html
<div ng-controller='PlaceCtrl'>
<h1>{{ title }}</h1>
</div>
JS
app.constant('FBURL', 'https://luminous-fire-8685.firebaseio.com/');
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/places/:placeId', {
templateUrl: 'views/place.html',
controller: 'PlaceCtrl'
})
}]);
app.factory('place', function($firebase, FBURL, $routeParams) {
var ref = new Firebase(FBURL + "places/" + $routeParams.placeId);
return {
id: $routeParams.placeId
}
});
app.controller('PlaceCtrl', function($scope, $rootScope, FBURL, $firebase, $location, $routeParams, place) {
$scope.placeId = place.id;
});

You're looking for ngRoute and $routeProvider. With those you can set up a parameterized route like this:
.when('/place/:placeId', { templateUrl: 'place.html', controller: 'PlaceCtrl' })
So every time a visitor hits a URL that starts with /place/ it ends up at PlaceCtrl and place.html. And the place ID is passed as a parameter.
Then you can pick up the parameter in your controller:
app.controller('PlaceCtrl', function($scope, FBURL, $firebase, $routeParams) {
var ref = new Firebase(FBURL+"places/"+$routeParams.placeId);
See also:
My sample application that uses AngularJS, Firebase and AngularFire: https://github.com/puf/trenches/blob/master/app.js (from which I copy/paste/modified the above snippets)
The AngularJS documentation for routeParams
The AngularJS tutorial's step on routing
The (way better) Thinkster.io tutorial page on routeParams

Related

vue.js json object array as data

aye folks!
I'm currently learning to do stuff with vue.js. unfortunately i'm stuck atm. what i want to do is sending a request to my sample API which responds with a simple json formatted object.
I want to have this object as data in my component – but it doesn't seem to do that for whatever reason.
Ofc i tried to find a solution on stackoverflow but maybe i'm just blind or this is just like the code other people wrote. i even found this example on the official vue website but they're doing the same thing as i do .. i guess?
btw. When i run the fetchData() function in a separate file it does work and i can access the data i got from my API. no changes in the code .. just no vue around it. i'm really confused right now because i don't know what the mistake is.
code:
var $persons = [];
and inside my component:
data: {
persons: $persons,
currentPerson: '',
modal: false
},
created: function() {
this.fetchData()
},
methods: {
fetchData: function () {
var ajax = new XMLHttpRequest()
ajax.open('GET', 'http://api.unseen.ninja/data/index.php')
ajax.onload = function() {
$persons = JSON.parse(ajax.responseText)
console.log($persons[0].fname)
}
ajax.send()
}
},
[...]
link to the complete code
First, make sure that the onload callback is actually firing. If the GET request causes an error, onload won't fire. (In your case, the error is CORS-related, see this post suggested by #Pradeepb).
Second, you need to reference the persons data property directly, not the $persons array that you initialized persons with.
It would look like this (inside your fetchData method):
var self = this;
ajax.onload = function() {
self.persons = JSON.parse(ajax.responseText)
console.log($persons[0].fname)
}

Angularjs - Append html code to body when URL changes

I'm working on single page aplication based on Angular. I want to do something like card stack made from divs. Like this.
Idea is that app will have some url links and card should be append when url changes. For example I have 4 links. Home | About | Contacts | Details
On page load will append home card then About etc. So url will change and next card should append.
So my question is: how append some html block when url changes in Angular? I mean that url will be changed but view should be the same and I want just append some html to existing view
Thanks
If using ui.router you can do it like this and update the scopes with the images.
Here is a code example
'use strict';
angular
.module('myApp', [
'ui.router'
])
.config(function ($locationProvider, $stateProvider, $urlRouterProvider, $compileProvider) {
// define states
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home.html'
})
.state('about', {
url: '/about',
templateUrl: 'views/about.html'
});
// define alternative route
$urlRouterProvider.otherwise('/');
})
.run(function ($rootScope) {
// image changes with route change
if(toState.url === '/') {
$rootScope.headerImg = 'images/headers/home.jpg';
} else if (toState.url === '/about') {
$rootScope.headerImg = 'images/headers/about.jpg';
} else {
$rootScope.headerImg = 'images/headers/error.jpg';
}
});
});

Calculating total-items in AngularJs Pagination (ui.bootstrap) doesn't work correctly

I use controllerAs and avoid using the $scope as a model.
I want to add pagination in my search result. I have a paging object in my controller as below, which will be shared with angular service and then with the server API.
vm.paging = {
pageNumber: 1,
pageSize: 10,
totalCount: 0
};
totalCount will be set by server and then be read from response.
My pagination in html:
<pagination total-items="ctrl.pageCount"
items-per-page="ctrl.paging.pageSize"
ng-model="ctrl.paging.pageNumber"
class="pagination-sm"
boundary-links="true"
ng-change="ctrl.find()">
</pagination>
I calculate pageCount in controller as below:
vm.pageCount = function () {
return Math.ceil(vm.paging.totalCount / vm.paging.pageSize);
};
But it doesn't work. when I set vm.pageCount = 1000; it works. It seems the problem is the function. How can I fix this problem? (the buttons are disabled and It should return 100 pages, not one! )
Update: Sample Plunker
you CAN use an Immediately Invoked Function Expression (IFEE) to get your vm.pageCount like so
ctrl.pageCount = (function() {
return Math.ceil(ctrl.paging.totalItems / ctrl.paging.pageSize);
})();
but you don't need to calculate pageCount and put it under total-items (the amount of pages in the pagination will be calculated automatically), you should provide it the length of you record array instead!
lets say if you get table data vm.data from http, you should place the length of this data inside total-items like so
total-items="vm.data.length"
HTML
<uib-pagination total-items="ctrl.paging.totalItems"
items-per-page="ctrl.paging.pageSize"
ng-model="ctrl.paging.pageNumber"
class="pagination-sm"
boundary-links="true"
ng-change="ctrl.find()">
</uib-pagination>
JS
ctrl.paging = {
pageNumber: 1,
pageSize: 10,
totalItems: response.length // this is your remote data
};
I've made this plunker for you
EDIT 1
since version 0.14.0, the directives are prefixed by uib-
Since version 0.14.0 we started to prefix all our components. If you are upgrading from ui-bootstrap 0.13.4 or earlier, check our migration guide.
so you should also use uib-pagination (instead of pagination) because your plunk uses the 1.3.2 version.
I did it! Of course, with the guidance of my colleague :) . As in my plunk (script.js), I hadn't Initialized the vm.paging object after the response, so the computing was based on default values in vm.paging. Since totalCount was 0, always the Division result was 1 and I had just one page. So I edited the vm.find body as below:
vm.find = function () {
vm.result.length = 0;
vm.findingPromise = myService.find(vm.filter, vm.paging);
vm.findingPromise
.then(function (response) {
vm.result = response.data.result;
// EDITED PART:
vm.paging = response.data.paging;
//
}, function (response) {
var r = response;
ngNotify.set('Some problems occurred!',
{
type: 'error',
position: 'top',
sticky: true
});
});
And also, I couldn't take advantages of uib-pagination, but when I replaced ui-bootstrap-tpls-1.3.2.min.js anywhere I was using ui-bootstrap-tpls.min.js before, it works correctly.
Also I removed the function of computing pageCount. With many thanks to svarog.

How to use Dynamic URL's to create Dynamic pages in Angular JS

I have put the question at the bottom as the only way I could explain my problem was with an example so with out the example it might not make sense but feel free to skip down to the bottom and just read the question.
I will use this example to try give some idea of what I do understand and where my understanding falls down.
I want to build a page where I can browse through a collection of items which I would set up like this:
angular.module('App')
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('browse', {
url: '/browse',
templateUrl: 'app/browse/browse.html',
controller: 'BrowseCtrl',
title: 'Browse',
mainClass: 'browse'
});
}]);
Each item is pulled through and place on this page using ng-repeat and then calling an api:
$scope.items = [];
$http.get('/api/items').success(function(items) {
$scope.items = items;
socket.syncUpdates('Item', $scope.items);
$scope.totalItems = $scope.items.length;
$scope.$watch('currentPage + itemsPerPage', function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
end = begin + $scope.itemsPerPage;
$scope.filteredItems = $scope.items.slice(begin, end);
});
});
This then accesses the api and repeats out the items. So far so good. Heres an example of the API setup. Worth mentioning I am using the Angular-fullstack generator which plugs in to Mongo DB using Express & Sockets.io
Item.find({}).remove(function() {
Item.create({
"image_url" : "../../../assets/images/test.jpg",
"title" : "Test Item",
"created_on" : new Date(2014, 9, 23, 3, 24, 56, 2),
"creator" : {
"profile_img" : "../../../assets/images/stephanie-walters.jpg",
"username" : "StephW",
"url" : "/stephanie-walters",
"first_name" : "Stephanie",
"last_name" : "Walters",
}
}
Ok now this is where things start to get unclear for me.
I now need to create the item pages, so that when I click on an item I get access to the content of that item. Short of creating every single page for every entry I would very much like to be able to create a page template that ui-router is able to attach content to when the correct url structure is met.
Thats probably not clear so let me try be a bit clearer. Lets say if we follow that JSON above I want to go to 'Stephanie Walters' profile I am going to need three things.Firstly a profile template, secondly I need the content for the profile in an api call and lastly a dynamic url that can take that api content and put it in to the page template.
Perhaps something similar to:
.state('profile.username', {
url: '/:username',
templateUrl: '/partials/profile.username.html',
controller: 'profileUsernameCtrl'
})
But I don't exactly understand how to get the take a variable like username from the item JSON(above) and then use that to build a URL /:username that connects to a template page profile.username.html and further still fill that page with the users content that is stored in another API call.
To "build a url" so to speak, you need to use the ui-sref directive.
Given a state like so:
.state('profile.username', {
url: '/:username',
templateUrl: '/partials/profile.username.html',
controller: 'profileUsernameCtrl'
})
to create a link to this state use:
<a ui-sref="profile.username({username: user.name})">{{ user.name }}</a>
where user is an attribute on the scope where that link is displayed.
For more complex URLs you just add additional parameters like so:
.state('browse.item', {
url: '/:username/:itemId'
})
To get the parameters you use the $stateParams service in your controller like so:
.controller('MyController', function($scope, $stateParams) {
$scope.username = $stateParams.username;
$scope.itemId = $stateParams.itemId;
})

using multiple json request with backbone.js

I have recently started working with backbone.js and i am finally started to get my head around after many tutorials.
One thing i am stuck on is how to use the routing to allow a list to pull different rest request.
Say i have the following in my collection
var NewsCollection = Backbone.Collection.extend({
model : News,
url: 'http://api.example.com/index.php/news/all/format/json',
});
From my understanding correct me if i am wrong backbone stores all the data pulled from the above feed into my model that extends this collection, this will all work i will pull in the feed and then display it in the view
This is where i get confused within my routing i have the following.
var NewsRouter = Backbone.Router.extend({
routes: {
"": "defaultRoute",
"news/:country_code":"updatedRoute"
},
defaultRoute: function () {
console.log("defaultRoute");
var movies = new NewsCollection()
new NewsView({ collection: movies });
movies.fetch();
//setInterval(function(){movies.fetch({success: function(){}});}, 60000);
},
updatedRoute:function (country_code) {
//confused
this.movie = this.movies.get(country_code);
}
})
I need to run the updatedRoute function when that will display a list of news based on cat of country code see below.
http://api.example.com/index.php/news/country/gb/format/json
How do i update the whole feed when a list item is click so the browser url would be.
http://localhost:8888/backbonetut/#news/gb
my list item is.
<li><a href='#news/gb'>GB</a></li>
I can get that in the updateRoute function with
this.movie = this.movies.get(country_code);
Can someone please help
You can either override the fetch function on your collection or temporarily change the url of the collection in your router action.