How init angularjs's $rootScope in multiply js files - javascript

Sorry, for my English.
I have angularjs app with many pages and forms.
For any page created file with Models for this page.
Example:
file userDict.js:
$rootScope.dicts.user = {
userTypes : { ... },
maxAge : ...,
minAge : ... ,
...
}
file companyDict.js:
$rootScope.dicts.company = {
companyTypes : { ... },
blabla : ...,
blabla : ... ,
...
}
files *Dict.js
....
....
And in UserController I use $rootScope.dicts.user, in CompanyController - $rootScope.dicts.company.
This is done for ease of separation large models.
But how to make that in each js models file calls $rootScope.dicts.??? = { ... } ?
How wrapping each file with models, that they calling during init app?
for example, if I wrote it using plane jQuery, I would do it so for each file
file userDict.js:
$(document).ready(function(){
$rootScope.dicts.user = {
userTypes : { ... },
maxAge : ...,
minAge : ... ,
...
}
});

If I clearly understood, what you want, you have two options to do it.
1) In the first option you should do it smth like this:
angular.module('myApp', [])
.run(function($rootScope) {
$rootScope.dicts = {};
$rootScope.dicts.user = "rootScope";
})
.controller('myCtrl', function($scope, $rootScope) {
$scope.userDict = $rootScope.dicts.user;
})
.controller('myCtrl2', function($scope, $rootScope) {
$scope.userDict = $rootScope.dicts.user;
});
This is JSFiddle for this example.
This code provide possibility to getting of $rootScope variables from any controller.
But you don't forget to inject $rootScope to controller.
2) The second option is using of shared service.
myApp.factory('sharedService', function () {
var sharedService = {};
sharedService.dict = {};
sharedService.dict.user = "any value";
return sharedService;
});
myApp.controller('FirstCtrl', function ($scope, sharedService) {
$scope.user = sharedService.dict.user;
});
myApp.controller('SecondCtrl', function ($scope, sharedService) {
$scope.user = sharedService.dict.user;
});

Based on #artyom-paranovich answer, i think you have 2 options.
The first and better solution is to put your data as a service. Note that Services aren't only for DB data but for general data as you are doing.
I would write an example but #artyom-paranovich did an excellent job for it.
My Advice that you will take this approach.
The second options is to wrap your data in div and to give that div a controller so it would be the parent of all of your sub controller. That way you can initiate your data in the parent controller and all your sub controller could have access to it
Your HTML:
<html ng-app>
<head>
....
</head>
<body>
<div ng-contoller="ParentController">
<div ng-contoller="subController1"> </div>
<div ng-contoller="subController2"> </div>
</div>
</body>
</html>
ParentController.js
myApp.controller('ParentController', function ($scopeScope) {
$rootScope.dicts.user = {
userTypes : { ... },
maxAge : ...,
minAge : ... ,
...
};
}
});

Related

Controller as syntax issues

I'm trying to use the Controller as syntax but I can't manage to make it work.
For example, here is a working code :
View :
<div ng-controller="ProjectsController">
Projects view : <br />
{{ projectsData }}
</div>
Controller :
angular.module('app')
.controller('ProjectsController', function($scope, Projects) {
Projects.get().then(function(result) {
$scope.projectsData = result.data;
});
});
And here is the Projects factory :
angular.module('app')
.factory('Projects', function($http) {
return {
get: function() {
return $http.get('http://localhost:8000/api/catalog/projects');
}
};
});
This way is working, using the normal syntax for controller and the $scope object inside of it.
But I can't get it to work when I'm using the Controller as syntax, like the following :
View :
<div ng-controller="ProjectsController as p">
Projects view : <br />
{{ p.projectsData }}
</div>
For the controller I tried :
angular.module('app')
.controller('ProjectsController', function(Projects) {
Projects.get().then(function(result) {
this.projectsData = result.data;
});
});
but also :
angular.module('app')
.controller('ProjectsController', function($scope, Projects) {
Projects.get().then(function(result) {
$scope.projectsData = result.data;
});
this.projectsData = $scope.projectsData;
});
But none of it worked, I had nothing in the view for {{ projectsData }}.
However, when I tried to test this as the controller using Controller as syntax :
angular.module('app')
.controller('ProjectsController', function($scope, Projects) {
Projects.get().then(function(result) {
$scope.projectsData = result.data;
});
console.log($scope.projectsData);
this.projectsData = "TEST";
});
I had my "TEST" displayed in the view, and $scope.projectsData was undefined.
So how can I set my controller in order to access it properly using the Controller as syntax ?
The problem is you need to store a reference of this in controller.
When you try to use this in a callback it has a different context
angular.module('app')
.controller('ProjectsController', function(Projects) {
var vm = this;
Projects.get().then(function(result) {
vm.projectsData = result.data;
});
});

Using AngularJS with a factory and a Controller

I'm trying to do the following:
When a user accesses "localhost/people/:id", the information about the respective person is taken from a MongoDB and displayed via Angular.
I have my api, which works perfectly fine, I've double-checked.
I'm using the latest AngularJS (1.4.9) and the new Router (angular-new-router or ngNewRouter).
I have an Angular module:
var personModule = angular.module('app.personDetailed', []);
a factory:
personModule.factory('personService', ['$http', function($http) {
return {
get : function(id) {
return $http.get('/api/people/' + id);
}
}
}]);
and a controller:
personModule.controller('PersonDetailedController', ['$routeParams', '$scope', 'personService', PersonDetailedController]);
function PersonDetailedController($routeParams, $scope, personService) {
var id = $routeParams.id;
personService.get(id).then(function(res) {
$scope.item = res.data;
});
}
This all should be displayed in this view:
<div data-ng-controller="PersonDetailedController">
<h2>{{ item }}</h2>
</div>
(yes, I'm not bothering trying to parse json yet).
The problem is, I am unable to use both $scope and $routeParams at the same time. I can only have one or the other. If I use both, the $scope works fine, but the $routeParams is empty.
Here's the main controller, just in case:
var appModule = angular.module('app', ['app.main', 'app.personDetailed', 'ngNewRouter', 'ngResource']);
appModule.controller('AppController', ['$router', AppController]);
function AppController($router) {
$router.config([
{ path: '/', component: 'main'}
{ path: '/people/:id', component: 'personDetailed'}
]);
}
Seems the new router does away with $scope and binds to the controller instance in the template instead.
Looks like you should use this instead
personModule.controller('PersonDetailedController', ['$routeParams', 'personService', PersonDetailedController]);
function PersonDetailedController($routeParams, personService) {
var personDetailed = this,
id = $routeParams.id;
personService.get(id).then(function(res) {
personDetailed.item = res.data;
});
}
and your view (do not use ng-controller)
<h2>{{ personDetailed.item }}</h2>

An elegant way of attaching a form helper to an Angular controller

UPDATE
moved to code review
I am looking for an elegant way of attaching a helper to my angular controller. I have followed this post and made some slight modifications to take $scope into account. This is what I have so far:
Here is my helper:
var productForm = {
helpers: {
setup: function($scope) {
this.$scope = $scope;
},
isInvalid: function(ngModel) {
return this.$scope.productForm[ngModel].$invalid && !this.$scope.productForm[ngModel].$pristine;
}
}
};
In my controller, I am doing the following:
intakeApp.controller("MageProductCtrl", ["$scope", "$http", function($scope, $http) {
$scope.helpers = productForm.helpers;
$scope.helpers.setup($scope);
...
}
in my view, I am referencing the helper as such:
<span class="help-block" ng-show="helpers.isInvalid('designer')">can't be blank</span>
Any room for improvement?

Angular list/detail view

I'm fairly new to Angular and I'm wondering how to go about creating a list/detail view using Angular routes as what I currently have doesn't seem to be working.
The app has a list of 'projects' and when you click on a project you see a detailed view of that selected project, standard stuff. I've got this working using ng-switch but ideally I want to use seperate routes for the list/detail views. I've read that for this I'm going to need to use a factory method but I'm having difficulty passing the selected data between the routes. Here's what I have:
app.factory('Project', [ function ($rootScope) {
var _selectedProject = {};
_selectedProject.project = {};
return _selectedProject;
}]);
app.controller('GalleryController', ['$scope', function ($scope, _selectedProject) {
$scope.sharedProject = _selectedProject || {};
$scope.selectProject = function (proj) {
_selectedProject.project = proj;
};
$scope.$watch('sharedProject', function (proj) {
$scope.chosenProject = proj;
})
}]);
I'm actually getting cannot set property 'property' of undefined which is inside $scope.selectedProject.
A nice solution for this is ui-router.
ui-router allows the nesting of states which correspond to controllers, urls and html templates.
In your example I would do the following:
Install ui-router (described in the link above)
Apply a configuration as follows:
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('project', {
url: "/project",
templateUrl: "partials/project/list.html",
controller: project_list_controller
})
.state('project.details', {
url: "/details",
templateUrl: "partials/project/details.html",
controller: project_detail_controller
})
}
Split your current controller into a project list controller and a project details controller.
Finally I would use a service to store your selectedProject as its a singleton, see the correct useage and differences between services and factories in this helpful blog post
Hope this helps.
You named your factory Project but are using _selectedProject as the injection to controller. You also didn't include it in the injection array
Controller should look more like:
app.controller('GalleryController', ['$scope','Project', function ($scope, Project) {
$scope.sharedProject = Project || {};
$scope.selectProject = function (proj) {
Project.project = proj;
};
$scope.$watch('sharedProject', function (proj) {
$scope.chosenProject = proj;
});
}]);

run a function when routed to specific rout Angularjs?

I am developing an application with angularjs what I need to do is to basically run some scripts when route is changed to a specific route I know that I can define a separate controller for each route. since, some routs are supposed to have shared data I shared a controller to between some of them
formApp.config(function($routeProvider) {
$routeProvider
.when('/firstUrl',{
templateUrl : 'firstURL',
controller : 'mainController'
})
.when('/secondURL' , {
templateUrl : 'secondURL',
controller : 'mainController'
})
}).run(function($rootScope, $location) {
$rootScope.$on("$routeChangeStart", function(event, next, current) {
if ( signed_in == false ) {
$location.path("/login");
}
});
});
The above is my config code,
MY QUESTION : I need to know if I can modify the code in the run() function, so that based on the route which user is redirected to some scripts are run.
or if this is not the right way to do that please correct me how do I have to solve this issue?
thanks in advance
I would recommend to create at least one controller per route. It makes the code more manageble.
Then you can define an init function that runs when each controller loads.
To share data between controllers you need to create a service, which is the correct way to do it rather then sharing the same controller for multiple paths.
It will also give you way more flexibilitywhen developing.
Update
Example
( Naming for example purposes only. Try to never do arrbitrary naming. )
#Service
angular.module('myService', [])
.factory('mSrv',[ function() {
return {
data: {
'first_name': 'John',
'last_name': 'Doe'
}
};
}])
;
#Controller1
angular.module('initMyCtrl1', ['myService'])
.controller('InitMyCtrl1', function( $scope, mSrv ) {
var initMyCtrl1 = function(){
console.log('runs on controller load')
console.log(mSrv.data);
};
initMyCtrl1();
})
;
#Controller2
angular.module('initMyCtrl2', ['myService'])
.controller('InitMyCtrl2', function( $scope, mSrv ) {
var initMyCtrl2 = function(){
console.log('runs on controller load')
console.log(mSrv.data);
};
initMyCtrl2();
})
;

Categories