Dynamically change the template url in angular js - angularjs

I'm developing a SPA in which data is stored in a JSON file. The JSON file also contains the link to the pages including ID. Whenever the user searches for an ID, the content of the page corresponding to that id should be loaded. How to do it?

Your search implementation should be separate, perhaps with a directive. There is no good answer to that, unless you have something to work with already.
However, the dynamic template loading can be achieved with a method that allows you to read URL parameters, such as ID, and re-direct accordingly. One of these methods is $location, whereas the best one for your case is $routeParams.
Here is an example:
const app = angular.module("app", ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/some_path/:ID', {
templateUrl: 'templates.html',
controller: 'templateCtrl'
});
}
(For more advanced control, switch ngRoute to ui-router library and adjust accordingly)
With this once your URL is in a form: www.example.com/some_path/10, it will re-direct you to that page with a $routeParams.ID value of "10".
In your template controller you can then use $routeParams to load your JSON file and fill in the $scope values of the page accordingly.
app.controller("templateCtrl", function ($scope, $routeParams, $http) {
var id = $routeParams.ID;
$http.get('myFile.json').
then((res) => {
// match your ID and load the data
let data = res.data;
let model;
for (let i = 0; i<data.length; i++){
if (data[i].id == id){
model = data[i].content;
break;
}
}
$scope.model = model;
});
});
If your want to wait until the data is loaded, before you display your page content, then use resolve in the config with appropriate factories / services that load your JSON files.

Related

AngularJS ngRoute - specify data for target page, with data not appearing in URL

I'm using AngularJS and I would like to redirect a user when he clicks a button on /page1 to /page2. I currently use AngularJS routing for this using ngRoute which works all fine. However, in addition to the redirection, I would also like to pass some data from page1 to page2 to pre-populate some of the HTML on page2. I know that in order to pass such data, I can either specify it in the path parameter,e.g.
/page2/<param1>/<param2>
or as a query string parameter, e.g.
/page2?<key1>=<value1>&<key2=value2>
In both ways, I can retrieve the query string or path params in /page2 using $route.current.params
However, I do not want to do either of the above as I do not want to expose my data on the URL to the user. Is there a way in AngularJS that the parameters can be passed to /page2, such that they are "hidden" from the URL?
Thanks
You can use a service to store data that will survive route changes. Services are singletons that persist through the entire life of the app.
app.service("appData", function() {
var myData;
this.set = function(data) {
myData = data;
};
this.get = function() {
return myData;
};
}
In a controller:
app.controller("viewCtrl", function($scope,appData) {
$scope.myData = appData.get();
//
appData.set(newData);
});
For more information, see AngularJS Developer Guide - Creating Services.

How to get rid of content flash using $firebaseObject

Currently I'm loading my firebase data right in my controller like this:
app.controller("MyCtrl", function ($scope, $firebaseObject) {
$scope.users = {};
var myDB = new Firebase('https://mydb.firebaseio.com/');
$firebaseObject(myDB.child("users")).$bindTo($scope, "user");
});
This way after the page is loaded, there is a delay during which the data is retrieved from firebase, therefore at first the page appears to be empty until the data arrives. This is unconvinient.
In order to prevent this flashy behavior I wanted to resolve the required data in my $routeProvider but wasn't able to get a promise.
How to properly get rid of the content flashing?
Is there a way to get a promise so one can resolve the $firebaseObject before the view is shown?
Please do not offer quick-and-dirty-solutions containing ng-cloak, ng-hide, ng-show etc.
You can use the $loaded() promise in your resolve function.
app.config(["$routeProvider", function($routeProvider) {
$routeProvider.when("/home", {
// the rest is the same for ui-router and ngRoute...
controller: "HomeCtrl",
templateUrl: "views/home.html",
resolve: {
"myObject": ["$firebaseObject", function($firebaseObject) {
var ref = new Firebase("...");
return $firebaseObject(ref).$loaded();
}]
}
})
https://www.firebase.com/docs/web/libraries/angular/guide/synchronized-objects.html
Check out the AngularFire docs on routing in authentication for better guidance on handling routes with promises in general.
https://www.firebase.com/docs/web/libraries/angular/guide/user-auth.html

Angular JS - Cannot identify the suitable place to put a piece of code that will be used by different pages

I am making a page that is extracting some information from the server and showing it on the interface. I am using angular js for this. So I have made a controller that has $http.get() method which gets data from the server and then the data binding is used to bind data to the html page. I am using this controller...
mission_vision_mod.controller('mission_visionCtrl', ['$scope','$http', function($scope, $http) {
$scope.visiontext = "Here is the content of vision";
$scope.bkclr = ['bk-clr-one','bk-clr-two','bk-clr-three','bk-clr-four'];
$scope.progressbar = ['progress-bar-warning','progress-bar-danger','progress-bar-success','progress-bar-primary'];
$scope.missioncount = ['col-md-0','col-md-12','col-md-6','col-md-4','col-md-3','col-md-2.5','col-md-2'];
$http.get('m_id.json').success(function(data){
$scope.missions = data;
$scope.len = data.length;
});
}]);
Now i want to make a page that allows the users to edit this info, this page also requires the same above code (code inside the controller). I also have to make a different controller for the new page to send whatever data that has been edited to server.
How do i use the above code for both the pages while i have to make a new controller for the second one for editing purpose. I want to use the same code for both the controllers.
I would suggest moving that code to a Service, then inject and use that service in each of the controllers where you need this functionality.
Services are often the best place to add code that is shared between multiple controllers or if you need a mechanism to pass data betweeen controllers.
Hope this helps!
Service/factory/value are meant for this , please refer the below example hope you get a better idea .
var app = angular.module('myApp',[]);
//controller
app.controller('myCtrl',myCtrl);
//inject dependencies
myCtrl.$inject = ["$scope","httpService"];
function myCtrl($scope,httpFactory){
$scope.data = httpFactory.getData;
}
//factory : http factory
app.factory('httpFactory',httpFactory);
//inject dependencies
httpFactory.$inject = ["$http"];
function httpFactory($http){
var datas = [];
return {
getData:function(){
$http.get('url').success(function(data){
datas.push(data);
}).
error(function(){
console.log('error');
});
return datas
}
}
}

Using routes in AngularJS to gather data

I have an single page app built on AngularJS which is configured using HTML5 routing.
So I use:
http://www.example.com/products rather than http://www.example.com/#/products
I also have wildcard subdomains affiliates can use for example:
http://myaffiliate.example.com
And I gather data about myaffiliate from a firebase using this controller:
app.controller("ReplicatedController", function($scope, $firebaseObject) {
var parts = location.hostname.split('.');
var refSubdomain = parts.shift();
var ref = new Firebase("https://example-firebase.firebaseio.com/" + refSubdomain);
var syncObject = $firebaseObject(ref);
syncObject.$bindTo($scope, "coach");
});
This all works fine but in addition to using a wildcard subdomain I also need affiliates to be able to use urls. For example:
http://example.com/myaffiliate
Is it possible to do this, and how do I do that?
You're going to need the $routeProvider service so you can send route parameters. Then you're able to do something like this.
.config(function($routeProvider){
$routeProvider.when('/:my_affiliate', {
//other route details
});
})
.controller('Ctrl', function($scope, $routeParams) {
console.log($routeParams.my_affiliate); // This will print affiliate
});

Loading data at startup and displaying via controller in AngularJS

I have a service which loads some data and then stores it into local storage, for a Angular base mobile app. I'm calling this service in the run function of my main JS file, like this:
angular.module('myApp', ['ionic'])
.config(function ($stateProvider, $urlRouterProvider) {
})
.run(function (StartupService) {
StartupService.initialDataLoad();
})
This data loads in to local storage, and then in the init function of the first views controller I try to access this data in local storage and display it in a list:
angular.module('MemberInduction').controller('InductionListCtrl', function($scope, DataAccessService) {
$scope.init = function init() {
if (localStorage.getItem('MI.ApplicationData') != null) {
var data = DataAccessService.getInductionList();
$scope.inductionsList = data;
} else {
$scope.displayReloadMsg = true;
}
}
$scope.init();
});
As you can see in my init() function I access the data through a service, but when the controller initialises the data maybe loaded in localStorage, but at the time of initialisation the data isn't there. So my displayReloadMsg flag is set to true, causing a message to the user telling them to reload the app to display the loaded data.
How can I get the view to initialise once the data has loaded successfully? So that the view and controller only load from localStorage once the data has loaded?
Thanks
Stephen
you want to use resolve on your main controller to make sure the data is loaded prior to accessing the controller.
See this example: https://thinkster.io/egghead/resolve-conventions
In the example below, the state transistion will not happen if the Flickr.search() returns no data - full source for this example is here - http://codepen.io/aaronksaunders/pen/gboQVO
.state('flickr-display', {
url: '/flickr-display:query',
templateUrl: 'flickr-display.html',
controller: 'FlickrDisplayCtrl as flkr',
resolve : {
ImageData : function($stateParams, Flickr) {
return Flickr.search($stateParams.query);
}
}

Resources