How load $http service app on startup in Ionic framework? - javascript

How load $http service app on startup in Ionic framework?
// This is a service
appModule.factory('NewGames', function($http, $ionicLoading) {
// JSON Array
var newGames = [];
var request = {'searchString' : 'name_fr'};
$http.get('http://example.com/rest/data.php', { cache: true}, request).success(function(response) {
newGames = response;
});
return {
all: function() {
//$ionicLoading.hide();
return newGames;
}
}
});
// This is a controller
myApp.controller('MainCtrl', function($scope, NewGames, $ionicSlideBoxDelegate, $stateParams, $ionicPlatform) {
$scope.nextSlide = function() {
$ionicSlideBoxDelegate.next();
}
$scope.newGames = NewGames.all();
});
If you press the button, the data is loaded. How to make so that the data was loaded at startup?

Use the ionic.Platform.ready() method, documented here.
You can run this method from anywhere in your app, may it be factory or controller.

Related

How can I execute a function in an angularJS controller from a backbone controller

I am working on a application originally created with backbone and jQuery, however due to client requirement, new modules are built with angular. Routing of the application is handled with backbone route and we have successfully integrated angular modules.
The actual problem is, I need to retrieve the current instance of a module in angular and execute a function from the controller of that module based on actions handled by a backbone controller.
Here is what my angular module and controller looks like:
//In chat.module.js
( function () {
angular
.module( 'chat.module', [] );
})();
//In chat.controller.js
(function () {
angular
.module('chat.module')
.controller('chat.controller', ['profileFactory', '$filter', '$q', '$timeout', 'Position', 'Chat', chat]);
function chat(profileFactory, $filter, $q, $timeout, Position, Chat) {
var vm = this;
vm.initChatFlag = false;
vm.initChat = initChat;
vm.setInformation = setInformation;
function setInformation() {
//handle business logic here
}
...
In backbone, the module is created as follows:
chatmodule: function () {
var self = this;
var element = angular.element(document.querySelector('#modalCallback'));
var chat = angular.element(document.querySelector('#chatModule'));
var isInitializedChat = chat.injector();
var isInitialized = element.injector();
if (!isInitialized) {
angular.bootstrap($('#modalCallback'), ['app']);
}
if (!isInitializedChat) {
angular.bootstrap($('#chatModule'), ['app']);
}
//TODO: chat.controller.setInformation() get access to fields like chat.controller.initChatFlag etc
The main app module is defined thus:
(function(){
angular
.module('app',[
'callback',
'ui.bootstrap',
'720kb.datepicker',
'ngLocale',
'directives.module',
'interceptor',
'directive.loading',
'angularUtils.directives.dirPagination',
'blog.module',
'profile.module',
'filters.module',
'chat.module',
'ui.toggle',
]);
})();
The AngularJS $injector is where a lot of the magic happens, so if you expose that outside of the AngularJS code you can hook it up to non-AngularJS code like the following:
//A simple AngularJS service:
app.service('myService', function() {
this.message = "This is my default message.";
});
//Expose the injector outside the angular app.
app.run(function($injector, $window) {
$window.angularInjector = $injector;
});
//Then use the injector to get access to the service.
//Make sure to wrap the code in a `$apply()` so an
//AngularJS digest cycle will run
function nonAngularEventHandler() {
angularInjector.invoke(function(myService, $rootScope) {
$rootScope.$apply(function() {
myService.message = "Now this is my message."
});
});
}
Edit: Alternatively, simplify the call like so.
//Instead of exposing the $injector directly, wrap it in a function
//which will do the $apply() for you.
app.run(function($injector, $window, $rootScope) {
$window.callInMyAngularApp = function(func) {
$rootScope.$apply(function() {
$injector.invoke(func);
});
}
});
//Then call that function with an injectable function like so.
function nonAngularClick() {
callInMyAngularApp(function(myService) {
myService.message = "Now this is my message."
});
}
//And remember if you're minifying, you'll want the minify-safe
//version of the injectable function like this
function nonAngularClick() {
callInMyAngularApp(['myService', function(myService) {
myService.message = "Now this is my message."
}]);
}
Update: (last one I promise!)
The above will work fine, but you might want to consider exposing a well-defined API instead of a generic injectable interface. Consider the following.
//Now I have a limited API defined in a service
app.service("myExternalApi", function($rootScope, myService) {
this.changeMyMessage = function(message) {
$rootScope.$apply(function() {
myService.message = message;
});
};
});
//And I just expose that API
app.run(function($window, myExternalApi) {
$window.myExternalApi = myExternalApi;
});
//And the call from outside of angular is much cleaner.
function nonAngularClick() {
myExternalApi.changeMyMessage("Now this is my message.");
}
I was able to get access to the controller using answer from this post - https://stackoverflow.com/a/21997129/7411342
var Chat = angular.element(document.querySelector('#chatModule')).scope();
if(!Chat) return;
if(Chat.chatCtrl.initChatFlag) {
Chat.chatCtrl.setInformation();
}else{
console.log('Chat has not been initialized');
}

Ways to use server date in an AngularJS application

Is there a "nice" way to set the server's date to an angularJS app?
Let's say that I have an API route to get this, sort of /api/date and I can call it with an angular service called dateService:
angular.module('myApp').service('DateService', ['$resource', function ($resource) {
return $resource('/api/date', { }, {
});
}]);
I need to get the date as soon as the app starts because my html file uses a function based on that date to display something. Otherwise I'll get an "undefined" error everytime I call it.
Thanks in advance
Have the back-end server return a timestamp in UTC.
Parse the timestamp value with var date = new Date(serverTimestampValue);
You now have a JS Date object that can be used with Angular Date filters.
If you are using ui-router for routing and if you need to learn the timestamp before showing anything to user you can use the resolve property of ui-router. Basically it resolves what you need before activating a state, and if you retrieve your server time in your parent state you can be sure that you will have the timestamp before anything starts in your application. Here is an example how to do it:
angular.module("yourApp").config(["$stateProvider", function ($stateProvider) {
$stateProvider
.state("topState", {
abstract: true,
template: "<ui-view></ui-view>",
controller: ["$rootScope", "serverTimestamp", function ($rootScope, serverTimestamp) {
$rootScope.serverTime = new Date(serverTimestamp);
//Do what you need to do with the server time, from now on you will have access to server time from each controller in your app.
}],
resolve: {
serverTimestamp: ["", function (bakkalBrandService) {
return yourService.retrieveTimestampFromServer();
}]
}
})
}])
You can do that in app.run
var app = angular.module('myApp',[]);
app.run(function ($rootScope, $state, DateService) {
// call date service and save it in $rootScope
});
You can delay the execution of angular app by manually bootstrapping it rather than auto initialization.
https://docs.angularjs.org/guide/bootstrap
This way you can do the following to get the server settings and have it available when your angular app starts.
//Define a global settings object. add proper namespace as per your app.
var myServerConfig = (function () {
var settings = {
someDefaultSetting: 'someDefaultValue'
};
return {
init: function (serverSettings) {
settings = $.extend(settings, serverSettings);
},
settings: settings
}
})();
//Define angular wrapper for your global object
var serverSettings = angular.module('server.settings', []);
serverSettings.factory('serverSettings', ['$window', function () {
return $window.myServerConfig.settings;
}]);
//On dom ready get all settings and bootstrap angular app
$(document).ready(function () {
//You will have to show some animation if you are making ajax call
//also if errors out handle that scenario
//Other option is to render settings from server on page load as mentioned in other answers
$.ajax({
type: 'GET',
url: '/api/settings',
error: function (error) {
//show user message that app cannot be loaded
},
success: function (setting) {
myServerConfig.init(setting);
bootStrapMyApp();
}
});
function bootStrapMyApp() {
angular.element(document).ready(function () {
angular.bootstrap(document, ['myApp']);
});
}
angular.module('myApp').service('DateService', ['$resource', function ($resource) {
this.date = null;
var self = this;
$resource('/api/date', { }, {
}).then(function(data){
self.date = data.date;
});
}]);
You can assign it to a service variable after you get it.
angular.module('myApp').service('DateService', ['$resource', function ($resource) {
this.date = null;
var self = this;
$resource('/api/date', { }, {
}).then(function(data){
self.date = data.date;
});
}]);
Then call the service to get it when you need it.
$scope.date = function() {
return DateService.date;
}

How to use a service with Http request in Angular JS

I'm using AngularJS to build my web application, I've been always using controllers to make HTTP request, which makes things easier and clear for me.
But for a better code structure, and better execution for my application, I wanted to use services instead of controllers to use the web service.
I tried to make :
var app = angular.module('ofcservices', []);
app.factory('news', ['$http', function ($http) {
var news={};
news.getnews= function () {
return $http.get('http://int.footballclub.orange.com/ofc/news?offset=0&limit=5');
};
return news;
}]);
and the code of the controller :
.controller('news', function($scope, ofcservices) {
$scope.news = ofcservices.getnews();
})
Everything seems to be right ?
ofcservices.getnews() is a promise You need manage with the function sucess and error
ofcservices.getnews().
success(function(data) {
$scope.news=data
}).
error(function(data, status, headers, config) {
//show a error
});
As weel change app.factory('news' to app.factory('newsFactory' and call it in controller('news', function($scope, newsFactory) {
You can get more data about promise in the angular documentation
The concept is more or less right, but you should use the callback functions to handle the $http response correctly.
But your controller and service have the same name news, which is BAD :-) and you need to inject the newsService and not the module name.
.controller('newsController', function($scope, newsService) {
newsService.getnews().then(
function(newsData) {
$scope.newsData = newsData
},
function optionalErrorhandler() {});
})
angular
.module('MyApp', [])
.controller('MyController', MyController)
.factory('MyService', MyService);
MyController.$inject = ['$scope','MyService'];
MyService.$inject = ['$http'];
function MyService($http){
var service = {
var myServiceFunction : function(){
$http({
// your http request on success return the data.
}).success(function(data)){
return data;
});
}
};
return service;
}
function MyController($scope, MyService){
MyService.myServiceFunction(); //Call service from the controller.
}

AngularJS App: Load data from JSON once and use it in several controllers

I'm working on a mobile app using AngularJS as a framework, currently I have a structure similar to this:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'homeCtrl'
})
.when('/one', {
templateUrl : 'pages/one.html',
controller : 'oneCtrl'
})
.when('/two', {
templateUrl : 'pages/two.html',
controller : 'twoCtrl'
});
}]);
app.controller('homeCtrl', ['$scope', function($scope) {
}]);
app.controller('oneCtrl', ['$scope', function($scope) {
}]);
app.controller('twoCtrl', ['$scope', function($scope) {
}]);
And then I'm displaying the content with an ng-view:
<div class="ng-view></div>
Things are working well but I need to load data from a JSON file to populate all the content of the app. What I want is to make and an AJAX call only once and then pass the data through all my different controllers. In my first attempt, I thought to create a Service with an $http.get() inside of it and include that in every controller, but it does not work because it makes a different ajax request everytime I inject and use the service. Since I'm new using angular I'm wondering what is the best way or the more "angular way" to achieve this without messing it up.
Edit: I'm adding the code of the service, which is just a simple $http.get request:
app.service('Data', ['$http', function($http) {
this.get = function() {
$http.get('data.json')
.success(function(result) {
return result;
})
}
});
Initialize the promise once, and return a reference to it:
No need to initialize another promise. $http returns one.
Just tack a .then() call on your promise to modify the result
angular.module('app', [])
.service('service', function($http){
this.promise = null;
function makeRequest() {
return $http.get('http://jsonplaceholder.typicode.com/posts/1')
.then(function(resp){
return resp.data;
});
}
this.getPromise = function(update){
if (update || !this.promise) {
this.promise = makeRequest();
}
return this.promise;
}
})
Codepen example
Edit: you may consider using $http cache instead. It can achieve the same results. From the docs:
If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.
Try this to get JSON Data from a GET Link:
(function (app) {
'use strict';
app.factory('myService', MyService);
MyService.$inject = ['$q', '$http'];
function MyService($q, $http) {
var data;
var service = {
getData: getData
};
return service;
//////////////////////////////////////
function getData(refresh) {
if (refresh || !data) {
return $http.get('your_source').then(function(data){
this.data = data;
return data;
})
}
else {
var deferrer = $q.defer();
deferrer.resolve(data);
return deferrer.promise;
}
}
}
}(angular.module('app')));
Now you can add this dependency in your controller file and use:
myService.getData().then(function(data){
//use data here
}, function(err){
//Handle error here
});

Pass $scope object to route, keep if refresh

Lets say i list all users in a list, when i click a user i want to route to a new view and get the data for the selected person.
What is the preferred way? Should i move the data i already got when i listed the users or should i create a new server call?
My first thought is to pass the data, but the problem with this is that the data the gets lost if the user refreshes the page.
What is the best practice to solve this?
Small example:
(function() {
var app = angular.module('app');
var controllerId = 'app.controllers.views.userList';
app.controller(controllerId, [
'$scope', 'UserService',function ($scope, userService) {
var vm = this;
vm.users = [];
userService.getAllUsers().success(function (data) {
vm.users= data.users;
});
var gotoUser = function(user) {
// Pass the user to UserDetail view.
}
}
]);
})();
<div data-ng-repeat="user in vm.users" ng-click="vm.gotoUser(user)">
<span>{{customer.firstname}} {{customer.lastname}}</span>
</div>
i now list the user details in UserDetail view, this view is now vulnerable against a browser refresh.
Typically most people just create a new server call, but I'll assume you're worried about performance. In this case you could create a service that provides the data and caches it in local storage.
On controller load, the controller can fetch the data from the service given the route params and then load the content. This will achieve both the effect of working on page refresh, and not needing an extra network request
Here's a simple example from one of my apps, error handling left out for simplicity, so use with caution
angular.
module('alienstreamApp')
.service('api', ['$http', '$q','$window', function($http, $q, $window) {
//meta data request functions
this.trending = function() {
}
this.request = function(url,params) {
var differed = $q.defer();
var storage = $window.localStorage;
var value = JSON.parse(storage.getItem(url+params))
if(value) {
differed.resolve(value);
} else {
$http.get("http://api.alienstream.com/"+url+"/?"+params)
.success(function(result){
differed.resolve(result);
storage.setItem(url+params,JSON.stringify(result))
})
}
return differed.promise;
}
}]);
I would say that you should start off simple and do a new server call when you hit the new route. My experience is that this simplifies development and you can put your effort on optimizing performance (or user experience...) where you will need it the most.
Something like this:
angular.module('app', ['ngRoute', 'ngResource'])
.factory('Users', function ($resource) {
return $resource('/api/Users/:userid', { userid: '#id' }, {
query: { method: 'GET', params: { userid: '' }, isArray: true }
});
});
.controller("UsersController",
['$scope', 'Users',
function ($scope, Users) {
$scope.loading = true;
$scope.users = Users.query(function () {
$scope.loading = false;
});
}]);
.controller("UserController",
['$scope', '$routeParams', 'Users',
function ($scope, $routeParams, Users) {
$scope.loading = true;
$scope.user = Users.get({ userid: $routeParams.userid }, function () {
$scope.loading = false;
});
$scope.submit = function () {
$scope.user.$update(function () {
alert("Saved ok!");
});
}
}]);
.config(
['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
.when('/users', {
templateUrl: '/users.html',
controller: 'UsersController'
})
.when('/users/:userid', {
templateUrl: '/user.html',
controller: 'UserController'
})
.otherwise({ redirectTo: '/users' });
}
]
);

Categories

Resources