I have been trying to inject $log in to a component created by a require statement for some client Angular.
var App = require('./app/containers/App');
var Header = require('./app/components/Header');
require('angular-ui-router');
var routesConfig = require('./routes');
import './index.css';
angular
.module('app', ['ui.router'])
.config(routesConfig)
.controller(App.App, ['$log'])
.service('todoService', todos.TodoService)
.component('app', App)
.component('headerComponent', Header);
The code for header is
module.exports = {
template: require('./Header.html'),
controller: Header,
bindings: {
todos: '='
}
};
/** #ngInject */
function Header(todoService) {
this.todoService = todoService;
}
Header.prototype = {
handleSave: function (text) {
if (text.length !== 0) {
this.todos = this.todoService.addTodo(text, this.todos);
}
}
};
~
The code for App is
module.exports = {
template: require('./App.html'),
controller: App
};
function App($log) {
this.log = $log;
$log.error('Hello from App');
}
I can inject $log as dependency for App as I have access to the controller. But attempting the same task for Header is difficult,because Header is created by require which does not seem to allow access to the controller function.
What I like to know is there a way round this?
I am trying to find a way of logging information from any possible javascript function in header.js.
I have seen any alternatives other than using $log to log information in a client side application
My solution so far has been to say in code written in the require block.
var ing = angular.injector(['ng']);
this.$log = ing.get('$log');
this.$log.error('I am a message');
I think this is the wrong way of doing things, it gives me what I want, but I expect it will break at some point. I find having access to $log is useful for debugging only. Its not sort of thing I need for any production code.
All I was trying to do was to get access to the $log angular wrapper. Turns out all I had to do was add $log to the argument list.
function Header(todoService,$log) {
$log.log('I am a log message');
this.todoService = todoService;
}
I am bit of a Angular 1.5 newbie and I had assume that you had to inject the $log to get the right response. Just declare it seems to be a bit of a kop out.
Related
I have two modules namely 'users' and 'groups', and have different routes in both of them. Now I want to use them in some other module, I am trying to require both the modules but getting error as required is not defined. How can I resolve it?
Here is my code:
appGroup.js
let myNinjaAppforGroup = angular.module('myNinjaAppforGroup',['ngRoute']);
//injected ngRoute module as a dependency in the above statement
myNinjaAppforGroup.config(['$routeProvider',function($routeProvider)
{
//code executes before application runs
$routeProvider
.when('/group/home',{
templateUrl:'views/home.html', //which view to be rendered if user visits this url
})
.when('/group/directory',{
templateUrl:'views/directory.html',
controller:'NinjaController'//it will be the controller for the mentioned route
}).otherwise({
redirectTo:'/group/home'
});
}]);
myNinjaAppforGroup.run(function()
{
//code executes when application runs
});
myNinjaAppforGroup.controller('NinjaController',['$scope','$http',function($scope,$http){
//scope is the glue between controller and view. Its also a dependency
$scope.message="Hey Angular!";//this is accessable in views
$scope.removeNinja = function(ninja)
{
let removedNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removedNinja,1);
}
$scope.addNinja = function()
{
$scope.ninjas.push({
name:$scope.newNinja.name,
rate:parseInt($scope.newNinja.rate),
belt:$scope.newNinja.belt,
available:true
});
$scope.newNinja.name="";
$scope.newNinja.rate="";
$scope.newNinja.belt="";
}
$http.get('model/ninjas.json').then(function(response){
$scope.ninjas=response.data;
//console.log(response); for checking the object received
//whatever data we are getting from the http service is being saved here.
})
}]);
module.exports = myNinjaAppforGroup;
`and appUsers.js`
let myNinjaAppforUsers = angular.module('myNinjaAppforUsers',['ngRoute']);
//injected ngRoute module as a dependency in the above statement
myNinjaAppforUsers.config(['$routeProvider',function($routeProvider)
{
//code executes before application runs
$routeProvider
.when('/user/home',{
templateUrl:'views/home.html', //which view to be rendered if user visits this url
})
.when('/user/directory',{
templateUrl:'views/directory.html',
controller:'NinjaController'//it will be the controller for the mentioned route
}).otherwise({
redirectTo:'/user/home'
});
}]);
myNinjaAppforUsers.run(function()
{
//code executes when application runs
});
myNinjaAppforUsers.controller('NinjaController',['$scope','$http',function($scope,$http){
//scope is the glue between controller and view. Its also a dependency
$scope.message="Hey Angular!";//this is accessable in views
$scope.removeNinja = function(ninja)
{
let removedNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removedNinja,1);
}
$scope.addNinja = function()
{
$scope.ninjas.push({
name:$scope.newNinja.name,
rate:parseInt($scope.newNinja.rate),
belt:$scope.newNinja.belt,
available:true
});
$scope.newNinja.name="";
$scope.newNinja.rate="";
$scope.newNinja.belt="";
}
$http.get('model/ninjas.json').then(function(response){
$scope.ninjas=response.data;
//console.log(response); for checking the object received
//whatever data we are getting from the http service is being saved here.
})
}]);
module.exports = myNinjaAppforUsers;
Now I have another file as app.js, I want to require these two files there, how can this be done?
Require doesn't work in browser.Basically require is a node_module by which we can access other modules or files.So please if you are using it on browser side then try other things like import or self.import or injecting.
Doc: http://requirejs.org/docs/download.html
Add this to your project: http://requirejs.org/docs/release/2.2.0/minified/require.js
and take a look at this http://requirejs.org/docs/api.html
i've been searching around for the last days but i cannot get closer to the solution. I try to mock the http response requested by the angular controller.
angular controller:
myController = function ($http, appConfig) {
$http.post(appConfig.restPath+"/administration/imports", {
}).then(function(data){
$scope.pagination = data;
$scope.totalItems = data.data.content.length;
$scope.totalPages = data.data.totalPages;
$scope.pages = [];
$scope.imports = data.data;
for (var i = 0; i < $scope.totalPages; i++){
$scope.pages.push(i);
}
});
}
and the test:
describe('Controller: myController', function() {
// load the controller's module
beforeEach(module("myModule"));
var controller,
scope, httpBackend, myPost;
// Initialize the controller and a mock scope
beforeEach(inject(function ($injector) {
httpBackend = $injector.get('$httpBackend');
myPost = httpBackend.whenPOST('http://localhost:9000/api/v1/administration/imports').respond({data: {content: ["a", "b"], totalPages: "1"}}, "");
scope = $injector.get('$rootScope');
var $controller = $injector.get('$controller');
createController = function() {
return $controller(myController, {'$scope' : scope });
};
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
it('should browse the list of imported files', function() {
httpBackend.expectPOST('http://localhost:9000/api/v1/administration/imports');
var controller = createController();
httpBackend.flush();
});
});
But it seems that he wants to ask the server for the real data when i inspect the test in the chrome console (network traffic -> HTTP requests shows me, that he is requesting the server instead of loading the mocked data...), but he receives 403 (forbidden).
the error i receive by karma is the following:
TypeError: Cannot read property 'length' of undefined at myController.js:35:40
line 35 is:
$scope.totalItems = data.data.content.length;
that makes me think that he tries to load the data from the REST service, receives 403, empty result (means data == {}) and then he tries to access on data.data.content.length which is undefined....
as you can see i did it exactly like google it recommends...
https://docs.angularjs.org/api/ngMock/service/$httpBackend
Other examples on SO or anywhere else look quite similar. What am i doing wrong?
yes you have to provide the real data or at least you can provide a prototype pf your data because you are testing that unit and it requires length.
and remove this part because you are mocking it twice
httpBackend.expectPOST('http://localhost:9000/api/v1/administration/imports');
use
myPost = httpBackend.expectPOST('http://localhost:9000/api/v1/administration/imports').respond({data: {content: ["a", "b"], totalPages: "1"}}, "");
this way you make sure that post is being called but if you still get same error then you have to check respond data.
My restangular call has a baseUrl set in a config file to http://localhost:3000/. So a call like
Restangular.all("awards").customPOST(award)
Calls at baseUrl+"awards"
Now when I write a test for this, i have to write:
httpBackend.expectPOST("http://localhost:3000/awards")
But later if this baseUrl changes, I will have to change it in a lot many .expect() methods.
Is there anyway to set a baseUrl for the expect method, in a config file somewhere?
So that the expect method something like-
httpBackend.expectPOST(baseUrl + "awards");
So that any change in the baseUrl does not require any change in the expect() method?
You can create an angular.constant and then inject that constant wherever it is required.
var app = angular.module('app', []);
app.constant('Configuration', {
BASE_URL: 'http://localhost:3000/'
});
app.factory('RestApiService', function($http, Configuration) {
var awardApi = Configuration.BASE_URL + '/awards';
return {
getAwards: fucntion() {
return $http.get(awardApi);
};
};
});
I tried to set a new controller in my Angular app, but I have this error coming:
[$injector:unpr] http://errors.angularjs.org/1.4.2/$injector/unpr?p0=successRedirectProvider%20%3C-%20successRedirect%20%3C-%20ingreCtrl.
I tried many things for a few hours but still have this issue.
Here's my files:
app.js:
var app = angular.module('app', ['formSubmit']);
app.factory('successRedirect', function(){
return function(data) {
if(data.status === "success") {
alert(data.message);
if (typeof(data.redirect) !== "undefined"){
document.location.href = data.redirect;
}
}else{
}
};
});
app.factory('errors', function(){
return function(data) {
alert(data.message)
for(var i = 0; i<data.errors.length;i++){
$('#new-page-form-container').append('<p>'+data.errors[i]+'</p>');
}
};
});
formApp.js:
var formSubmit = angular.module('formSubmit', ['ckeditor', 'ngFileUpload']);
ingredientsCtrl.js:
formSubmit.controller('ingreCtrl', ['$scope', '$filter', '$http', 'successRedirect', 'errors', function ($scope, $filter, $http, successRedirect, errors) {
}]);
You're trying to use the successRedirect service of the app module inside your formSubmit module. That means you need to dependency inject app into formSubmit:
var formSubmit = angular.module('formSubmit', ['app', 'creditor', 'ngFileUpload']);
^^^^^
Not the other way around.
I finally found why it doesn't work, last week I did another module for the login system in my web site in another file, and I didn't remember that I already gave the name 'app' to this module, so I change my module's name in the file app.js and it works.
But to answer to some comments, my dependency injection was good, as my inclusion, no need to change the order. The problem was the module name.
Thanks anyway for your time, subject close ^^
The angular project I am working on is adding a configuration file to it. The configuration file is loaded as a JSON, it contains strings that will be replacing the static strings that are currently used in the current version of the project. There is multiple modules where the JSON's data needs to be used, what would be the best way to make the JSON file global throughout the project? I was thinking about loading it separately in each module using a HTTP GET, but I need the JSON to be loaded before everything else.
Thanks.
You probably can use a service. define a object on the scope and on that define the JSON. create a function which returns the JSON and inject it wherever the need arises. Implementation maybe like:
app.service("commonService", ["$log", function($log){
this.myConfiguration = {
id:"0",
name:"abc"
};
this.mystatic = function(){
return myConfiguration;
}
}
Now you can inject it and use in a controller as:
app.controller("mycontroller", function($scope, commonService){
$scope.static = commonService.myStatic();
//other code here
});
you can use value:
// create the module as usual
angular.module("myapp",[/*...*/]);
// on any other app point, set your json:
angular.module("myapp").value("myjson",{/*...*/});
If you don't need is before you do any routing you could use a service. This is what a config service could look like:
(untested)
app.service('ConfigService', function ($q, $http) {
// loads the config file
this.loadConfig: function() {
var deferred = $q.defer();
if(angular.isDefined(this.config) && this.config.length){
deferred.resolve(this.config);
}
$http.get('config.json')
.success(function(response) {
this.config = response;
deferred.resolve(this.config);
})
.error(function(){
deferred.reject('Could not load "config.json" file');
});
return deferred.promise;
};
// returns a config setting
this.get: function(key){
// if the config is not loaded yet, load it and call self
if(!angular.isDefined(this.config) || !this.config.length){
this.loadConfig().then(function(){
return this.get(key);
})
}
// config is loaded. Return requested key
if(angular.isDefined(config[key])){
return config[key];
}else{
console.error( 'Could not load config value: ' + key );
return false;
}
};
});