I bought an app. I'm new with Javascript and AngularJS. I'm trying to following the code but I don't understand how the function on homeService.js knows that has to use remote-data.service.js
This is the home.controller.js
...
(function activate() {
...
loadCategories();
...
})();
...
// ...............................
function loadCategories() {
debugger;
homeService.getFeaturedCategories()
.then(function(categories) {
vm.categories = categories;
});
}
The function call homeService.getFeaturedCategories(). So....
home.service.js
function getFeaturedCategories() {
return dataService.getFeaturedCategories();
}
The function call to dataService.getFeaturedCategories()
Here is when data.service.js call to a remoteDataService.js and this file make the hhtp.get (I paste the full code of data.service.js):
(function() {
'use strict';
angular
.module('restaurant.common')
.factory('dataService', dataService);
dataService.$inject = ['ENV', '$injector'];
/* #ngInject */
function dataService(ENV, $injector) {
switch(ENV.dataProvider) {
case 'LOCAL':
return $injector.get('localDataService');
case 'REMOTE':
return $injector.get('remoteDataService');
case 'FIREBASE':
return $injector.get('firebaseDataService');
}
throw new Error('Data provider is not valid');
}
})();
I wanna know:
How the function returns remoteDataService.
Also I wanna know how make that only the function dataService.getFeaturedCategories() in the home.service.js make that dataservice return a localDataService. Because I wanna load a local JSON (not make a http.get)
Thanks!
Don't understand question. Your data service read ENV.dataProvider once, and return proper service. It's unable to return different services for different calls in current implementation.
you should use "localDataService" in home.service instead of "dataService". Just change names.
In your Home.service you should have lines like:
homeService.$inject = ['dataService'];
function homeService(dataService){
...
}
change it to: (order of $inject and arguments should be same.)
homeService.$inject = ['dataService', 'localDataService'];
function homeService(dataService, localDataService){
...
}
and use localDataService in your fn.
Related
I am having one condition i.e
if(localstorage.testEnv){
env.apiUrl='testUrl.com';
}else{
env.apiUrl='liveUrl.com';
}
I need to inject this code in all the services. Is there any way I can implement this so that their won't be any code duplication.
Also, would this code work? I am trying to update env const (apiUrl) here?
Simplest way is to make a Utils Service and expose all common functions in this file, in this case a function which checks testEnv from local Storage and returns the corresponding URL. In this case getAPIBaseUrl is the function.
define(["../module"], function(services) {
"use strict";
services.service("Utils", [
"$localStorage",
function($localStorage) {
this.getAPIBaseUrl = function() {
if ($localStorage.testEnv) {
return "testUrl.com";
}
return "liveUrl.com";
};
}
]);
});
Unless the API url can change in the runtime, you may want to define the apiUrl and an AngularJS constant.
var app = angular.module('app', []);
app.constant('apiUrl', (function() {
return localStorage.testEnv ? 'testUrl.com' : 'liveUrl.com'
})());
app.controller('SomeController', function(apiUrl) {
console.log(apiUrl)
});
Main benefit of using a constant is that it can be injected in the configuration phase, e.g:
app.config(function(apiUrl) {
console.log(apiUrl)
})
I have a code snippet below.
sample.js
(function() {
/*global angular */
'use strict';
angular.module('myapp', ['spinner'])
.controller('myCtrl', ['$scope', '$window', function ($scope, $window ) {
$scope.methodname = function() {
if(something){
/* Doing some operations */
}
};
/* Here I need to define the callme javascript function */
function callme(response){
/* If I call like this, I'm getting error in console. */
}
}]); /* Controller ends here */
/* Creating a new anonymous function to perform some operations */
(function () {
'use strict';
/* Edited */
code.util.myHTTP(url, function (response) {
// Adding response to session storage
callme(response);
}, function () {
// Removing from session storage
});
})();
}());
Here, I can't able to call callme javascript function inside angular controller . I'm getting error in console like
Uncaught ReferenceError: callme is not defined
Is there any way to achieve this?
I need to use some controller parameters like $window inside callme function, that's why I'm defining callme function inside controller.
I have run function in my js file already like below
.run(function($rootScope, $log, $window) {
});
My requirement is like call anonymous function, on load there will be some api response, I need to call one method to process the response. because of these controller parameters, I wanted to define my method inside the controller. Is there any alternate way to achieve this?
Your indentation is all over the place and is what makes this code hard to understand. Here's your correctly formatted code..
(function () {
/*global angular */
'use strict';
angular.module('myapp', ['spinner'])
.controller('myCtrl', ['$scope', '$window', function ($scope, $window) {
$scope.methodname = function () {
if (something) {
/* Doing some operations */
}
};
/* Here I need to define the callme javascript function */
function callme (response) {
/* If I call like this, I'm getting error in console. */
}
}]); /* Controller ends here */
/* Creating a new anonymous function to perform some operations */
(function () {
'use strict';
/* Edited */
code.util.myHTTP(url, function (response) {
// Adding response to session storage
callme(response);
}, function () {
// Removing from session storage
});
})();
}());
The reason this doesn't work is because function declarations are hoisted to the top of their scope, but do not exist outside of that scope. If we remove some cruft, this is what your code simplifies to:
(function() {
function MyController($scope) {
$scope.methodname = function() {}
function callme(response) {
}
}
(function() {
callme()
}())
}())
callme is hoisted, but only to the top of MyController. That symbol doesn't exist outside of that scope, and that's why you can't do callme() in your nested scope.
What you are doing seems like an anti-pattern; even if you could achieve this, core.util.myHTTP would not execute within the Angular digest cycle, so you'd have to call $scope.$apply inside of your controller, which is generally considered a bad thing. Why not just use $http instead?
Nevertheless, if you really want to do this (and you don't), you could define your function like so:
(function() {
function callme(response) { }
function MyController($scope) {}
(function() {
...
callme()
}())
}())
Alternatively you could use directives (or components, depending on your angular version) to handle this instead.. which is how it should be done.
function SpinnerCtrl($http) {
this.$http = $http
}
SpinnerCtrl.$inject = ['$http']
SpinnerCtrl.onInit = function onInit() {
var that = this
return this.$http.get(url)
.then(function (response) {
// Store it in session storage, do whatever.
// Presumably there's some data you want to make accessible to other parts of the app, so I assign it to the controller here
that.response = response
})
}
angular.module('myapp', ['spinner'])
.component('spinner', {
controller: SpinnerCtrl,
template: '<h1>{{ $ctrl.response }}</h1>'
})
// or
function SpinnerCtrl($scope, $http) {
return $http.get(url).then(function (response) {
$scope.response = response
})
}
angular.module('myapp', ['spinner'])
.directive('spinner', function () {
return {
controller: SpinnerCtrl,
template: '<h1>{{ response }}</h1>'
}
})
Note that really you should move the $http call to a service and handle the session storage in there too; the session storage thing is implementation detail and the component/directive using it should not have to care. I haven't done that just for brevity.
I wrote a small Angular1 app which has a Database service that is using LokiJS.
I was wondering if there is a way to dynamically add properties/functions to a Service/Factory.
I'm trying to add dynamic getter for every collection that is created via this Service.
Here my example:
Database.js
angular.module('MyApp')
.factory('Database', ['$log', '$q', 'Loki',
function Database($log, $q, Loki)
{
var _db,
dbInitialized = false;
function init(config)
{
// some logic here
}
function addCollection(name, cfg) {
// some logic here
_db.addCollection(name, cfg);
// this doesnt work, but is desired ->
/*this['get'+name] = this.getCollection.bind(this, name);*/
}
function getCollection(collectionName) {
// some logic here
return something;
}
return {
init: init,
addCollection: addCollection,
getCollection: getCollection
};
}
]
);
app.js
angular
.module('MyApp', ['lokijs'])
.run(['Database',
function (Database) {
Database.init();
Database.addCollection("MyCollection", {});
// then fill collection, afterwards ->
var collection = Database.getCollection("MyCollection");
// I would like to use Database.getMyCollection()
}]);;
Is there a way to modify a initialized Service/Factory?
The most appropriate place for that is decorator
app.decorator('Database', ['$delegate', function ($delegate) {
var Database = $delegate;
Database.init();
Database.addCollection("MyCollection", {});
...
return Database;
}]);
The recipe doesn't really differs from run block, but it guarantees that service will be initialized on injection, while run blocks depend on their order.
I'm using a framework called Radiant UI, which is a way to get HTML5 UI into Unreal Engine 4. I'm trying to pick up some modern Javascript while I do that, so I'm building the UI in AngularJS.
My understanding of Angular is still pretty weak though, and I'm a bit confused about what the best practice is here. The extension injects the following Javascript when it sets up.
var RadiantUI;
if (!RadiantUI)
RadiantUI = {};
(function() {
RadiantUI.TriggerEvent = function() {
native function TriggerEvent();
return TriggerEvent(Array.prototype.slice.call(arguments));
};
RadiantUI.SetCallback = function(name, callback) {
native function SetHook();
return SetHook(name, callback);
};
RadiantUI.RemoveCallback = function(name) {
native function RemoveHook();
return RemoveHook(name);
};
})();;
So this is simply pushing RadiantUI into the global namespace. That would be fine if the extension was always there, but it isn't. In the test environment (Chrome), it's not there. It's only there when running in the game engine. That, combined with the fact that globals suck, means I want to encapsulate it.
In the previous iteration of this, I had it wrapped in an AMD module, and it worked well. Like this:
define([], function()
{
if ("RadiantUI" in window)
{
console.log("RadiantUI in global scope already!");
return window.RadiantUI;
}
var RadiantUI;
if (!RadiantUI) {
RadiantUI = {};
RadiantUI.TriggerEvent = function() {}
RadiantUI.SetCallback = function() {}
RadiantUI.RemoveCallback = function() {}
}
console.log("Using fake RadiantUI bindings");
return RadiantUI;
});
So here's what I want to do:
I want to include radiant as a dependency to my app/stateProvider and have it injected, much the same way it would be in AMD. With the stub methods in place if the extension isn't present. What's the proper approach to this? A module? A service provider?
UPDATE: This is the working code using the answer given.
var myapp = angular.module('bsgcProtoApp', ['ui.router' ]);
myapp.value('radiant', window.RadiantUI || {
TriggerEvent: function()
{
console.log("TriggerEvent called");
},
SetCallback: function(name, callback)
{
console.log("Setcallback called");
},
RemoveCallback: function(name)
{
console.log("RemoveCallback called");
}
});
myapp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider )
{
$urlRouterProvider.otherwise("/mainmenu");
$stateProvider.state('mainmenu',
{
name: "mainmenu",
url: "/mainmenu",
templateUrl: 'templates/mainmenu.html',
controller: ['$scope', 'radiant', function($scope, radiant)
{
$scope.tester = function()
{
radiant.TriggerEvent("DuderDude");
console.log("Duder!");
}
}],
});
}]);
You presumably have an Angular module or app. For the sake of this answer, let's call it MyApp.
Now you can do
MyApp.value("RadiantUI", window.RadiantUI || {
TriggerEvent = function(){},
//... more properties
});
Now to access this value as a dependency in a controller for example, you'd do this
MyApp.controller(["$scope", "RadiantUI", function($scope, RadiantUI){
// ... controller code ...
}]);
I need to write & manage a lot of JavaScript code for current project.
I separate them into multiple .js files mainly based on module.
So, now i have for example:
Map.js // deal with google map issue
Common.js // common functions that will share by all modules
User.js // user module js code
Geofence.js // geofence module js code
etc.....
For example, inside my User.js file
what if i want to declare a function that only used inside the User.js file, not accessible by outside. what can i do?
var User = {};
User.registerModule = function () {
$('#user').click(function () {
Common.showLeftScrollbar();
getAllUsers();
// ...
});
}
function getAllUsers(){ // how to hide this function
// get
return users;
}
So, in my home page, i only need to coordinate with multiple .js files. Access what allows to access.
$(document).ready(function (data) {
GoogleMap.initialiseGoogleMap();
Common.refreshRightScrollbar();
User.registerModule();
// ...
});
It is my first time to write js and not enough time to study a whole book. So, please, in your opinion, is this structure ok with many js code? and how to hide functions that i dont want outside to access?
to hide that function you have different possibilities
just enclose your code in an immediate self-executed anonymous function
var User = {}; // this should not be enclosed too
(function() {
User.registerModule = function () {
$('#user').click(function () {
Common.showLeftScrollbar();
getAllUsers();
// ...
});
}
function getAllUsers(){ // how to hide this function
// get
return users;
}
})();
enclose that function inside User.registerModule function
User.registerModule = function () {
function getAllUsers() { ... }
$('#user').click(function () {
Common.showLeftScrollbar();
getAllUsers();
// ...
});
}
Place this function inside the scope:
User.registerModule = function () {
function getAllUsers(){ // how to hide this function
// get
return users;
}
$('#user').click(function () {
Common.showLeftScrollbar();
getAllUsers(); // returns users
// ...
});
}
And it will be private.
Now if you try to call this function outside it will be undefined:
getAllUsers(); // undefined.