Using routes in AngularJS to gather data - angularjs

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
});

Related

Dynamically change the template url in angular js

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.

Angularjs, global Service throwing error

Stuck in a situation, my app is configured in a way, that I have an app controller, which is using ng-route to route between different views and partials, Now from the login controller, I am making a request to get some data, now I want that data to be accessed globally in the application. Now when I create a service, I am injecting it in the app controller module, but I am getting an error service is not defined,
My app.js:
var myApp = angular.module('app', ['loginMod', 'dashboardMod', 'newRequestMod', 'ngAnimate', 'ui.bootstrap', 'ngRoute', 'userDetailService']);
myApp .config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: 'resources/pages/login.html',
controller:'loginController'
})
...
Now in my logincontroller i am using the service :
userDetailShareService.sendData(loginModel);
console.log("Checking the service if it works " + userDetailShareService.getData);
userDetailShareService.js:
var app = angular.module('userDetailService',[]);
app.factory('userDetailShareService', function($timeout,$rootScope) {
var service = {};
var dataArray = [];
service.data = [];
service.sendData = function(data){
//dataArray.push(data);
dataArray=this.data;
};
service.getData = function(){
return dataArray;
};
return service;
});
No I am not sure what is throwing that error, the app.js is the first page that is hit, and the data mentioned in login controller is some response data, that I am getting in login controller and then I want to share across my entire application, every controller the data that I get, I do not want to use $rootScope as it will burden the same.
Could anybody please reply, I am in a great need. Thanks in advance.

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

Best practice of RestAngular

So I've started to work on an own project, where I'm in the middle of developing the front-end of my website. I started out with an PHP Laravel back-end and I've setted up an API service for my database.
With a hybrid app in mind, i started using angularjs for my front-end web application. For the communication with my API using REST, I've came across restangular, which is pretty nice because it was exactly what I hoped for.
There is only one issue that bothers me, there is no real "guide" how to setup a maintainable module/factory/provider/service to replicate your api with a system that stores the data in local storage or setup simple system where you could inject the "Model" into an controller and just do Model->getAll() to fetching all models.
Because I'm new to angularJS, and therefor my knowedge on how to appeach this, is fairly limited. So far I've made this:
main application
var client = angular.module('clientApp', ['angulartics', 'angulartics.google.analytics', 'ngRoute', 'restangular']);
client.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
controller: 'flongsController',
templateUrl: '/client_partials/Homepage.html'
})
.when('/flongs/:slug', {
controller: 'flongsController',
templateUrl: 'client_partials/Flong.html'
})
.otherwise({
redirectTo: '/'
});
}]);
flongsController
client.controller('flongsController', ['$scope', 'Restangular', '$routeParams', function ($scope, Restangular, $routeParams) {
//controller variables
var baseFlongs = Restangular.all('flongs');
$scope.flongs = {};
init();
function init() {
baseFlongs.getList().then(function(flongs){
$scope.flongs = flongs;
});
}
}]);
So, my question is simple:
How can i improve this code so that its more efficient and more maintainable?
Thanks in advance,
Nick van der Meij
First of all do not use service logic on the controller, instead use angular services for this purpose.
Let me share you how I build my projects,
First build Restangular Service :
angular.module('example').factory('exampleService', ['Restangular', function(Restangular){
// this is service object with list of methods in it
// this object will be used by controller
var service = {
getExamples: getExamples,
getExample: getExample
};
// get examples from server by using Restangular
function getExamples(){
return Restangular.all('examples').getList();
}
// get example with given id from server by using Restangular
function getExample(exampleId){
return Restangular.one('examples', exampleId).get();
}
return service;
}]);
here we build exampleService now let's inject it into a controller
angular.controller('ExampleCtrl', ['exampleService', function(exampleService){
// get examples by using exampleService
exampleService.getExamples().then(function (examples) {
$scope.examples = examples;
});
// get example with given id by using exampleService
exampleService.getExample('1234').then(function (example) {
$scope.example = example;
});
}]);
This is how I use it basically. For more advanced usage you can look the examples in Restangular Github Page.

Inject routes dynamically in angularjs

I'm using angular to dynamically create another angular app. I was wondering if there is a way to inject routes dynamically. Something like
angular.module('app').controller('CreateCtrl', function ($scope,$routeProvider) {
var count = 0;
$scope.addPage = function(){
$routeProvider.when('/'+count, {
templateUrl: 'views/created.html',
controller: 'CreatedCtrl'
});
count++;
};
});
I know this code is silly but I hope it transmits what I'm trying to do. When user intercts with the application he/she will create new routes... is that possible?
There are two ways:
Option 1
modifying the routes object directly, as suggested in https://stackoverflow.com/a/13173667/17815
$route.routes['/dynamic'] = {templateUrl: 'dynamic.tpl.html'};
Be careful: you need to add both "/newurl" and "/newurl/" (with trailing slash).
see the angular code:
this.when = function(path, route) {
routes[path] = extend({reloadOnSearch: true}, route);
// create redirection for trailing slashes
if (path) {
var redirectPath = (path[path.length-1] == '/')
? path.substr(0, path.length-1)
: path +'/';
routes[redirectPath] = {redirectTo: path};
}
return this;
};
Option 2
you can keep a reference to $routeProvider:
var $routeProviderReference;
var app = angular.module('myApp', ['myApp.controllers']);
app.config(['$routeProvider', function($routeProvider) {
$routeProviderReference = $routeProvider;
}]);
See http://blog.brunoscopelliti.com/how-to-defer-route-definition-in-an-angularjs-web-app
This is polluting the global namespace but you still use the interface to mutate the routes object. I guess this makes it easier to maintain.
Maybe you can try to put it in a closure.
In any case, keep in mind that you are expected to do it in a provider to make the application robust. "define before use".

Resources