Angularjs passing value from one module to another module - angularjs

I am using Angularjs for my application and I would like to transfer the data between the modules, tried all the ways, but the data is not getting passed. Please have a look at my code here.
I have a page called departments in frontapp module, while clicking on particular department, I want to pass the department Id to departmentapp module where each department will have its own page.
<h5>{{school.schoolName}}</h5>
<ul data-ng-repeat="department in school.departments">
<li data-ng-click="getdepartmentBydepartmentId(department.departmentId);setDepartmentId(department.departmentId)">
{{department.departName}}
</li>
The code of Controller
$scope.getdepartmentBydepartmentId = function(departmentId){
SchoolService.getdepartmentBydepartmentId(departmentId).then(function(response){
$scope.department= response.data;
});
}
$scope.getDepartmentId=function(){
SchoolService.getDepartmentId().then(function(response){
$scope.departmentId = response.data;
});
}
$scope.setDepartmentId=function(departmentId)
{
//Some authentication code...
alert(departmentId);
SchoolService.setDepartmentId(departmentId);
alert(SchoolService.getDepartmentId());
//Here I want to pass the username to homectrl.js
window.location.href="./department"
}
The code in services js file
obj.getDepartmentId=function(){
return departmentIDSchool;
};
obj.setDepartmentId=function(departmentID){
// var departmentID = null;
departmentIDSchool = departmentID;
};
obj.getdepartmentBydepartmentId=function(departmentId){
return $http.post('getdepartmentBydepartmentId?departmentId='+departmentId);
};
In departmentapp module - departmentcontroller.js
app.controller("SchoolController", SchoolController);
app.service("SchoolService",SchoolService);
angular.module("frontApp").SchoolService.getDepartmentId().then(function(response){
$scope.departmentId = response.data;
alert($scope.departmentId);
});
But here departmentId I am not getting. After going through many questions at stack overflow, I come to know that in service layer we need to have getter and setter, but even after placing that it is not working. Can some one help me here?

You can pass a variable like that easily in the router
$routeProvider.when('/:primaryNav/:secondaryNav', {
templateUrl: 'resources/angular/templates/nav/'+$routeParams.primaryNav+'/'+$routeParams.secondaryNav+'.html'
});
See the $routeParams in templateUrl, you can also inject it into your controller to get the params.

Related

Difference between using a service and a controller in Angular

Its my first first time using javascript and angular.
So Im developing a web page with angular, and I wrote a Controller like this:
/*BrandController to manage the html content of a single brand */
.controller('BrandController', [function(){
this.brand = {};
this.isSet = function(checkBrand) {
return this.origin === checkBrand;
};
this.setBrand = function(activeBrand) {
this.brand = activeBrand;
};
}])
I have some tabs of brands and when I click one, that brand is assigned with the controller.
<a href ng-click="BrandController.setBrand(brand)">
<h4>{{brand.name}}</h4></a>
And I show its content like this:
<b>Nombre</b><br>
{{BrandController.brand.name}}<br><br>
<b>Marca</b><br>
{{BrandController.brand.brand}}<br><br>
So, It works the way I wanted, but a friend told me this was not the correct way to do it. That I have to create a service, to pass the information of brand. And we got it like this:
/* BrandController to manage the html content of a single brand */
.controller('BrandController', function(BrandService, $scope){
$scope.brand = {
};
$scope.setBrand = function(brand){
$scope.brand = brand;
};
$scope.isSet = function(brand){
return $scope.brand === brand;
};
})
.service('BrandService', function(){
var brand = {};
var isSet = function(checkBrand) {
return brand === checkBrand;
};
var setBrand = function(activeBrand) {
brand = activeBrand;
};
return{
isSet: isSet,
setBrand: setBrand
};
});
This works too, as you can see is much more code, and I could not to understand why should I create a service instead.
So, If you can explain in my example what is the best way to do it and why I would be very grateful.
Thank you.
There are some situation while service are really usefull.
with a service you can abstract the logic to read data keeping your controller standard. In case your data structure change you can change the logic in the service without touching the controller(and potentially the view).
The controller is responsible for binding data to the view and should not care about how the data are received or structurated.
Service are also singleton so you can store data cross controller or between controller and directives.
Most used application of those concepts are data services. here you can find a good documentation explaining the best practice and some logical advantages.
hope this helps

Setting up dynamic $http.get request (Angular)

I want to know how to dynamically change an $http call so that the $http request URL differs based on the element that is clicked in an ng-repeat list. But I'm stuck.
Currently, I have an ng-repeat set up on my index page:
<div ng-repeat="team in nt.getStandings">
<h2>{{team.team_name}}</h2>
<p>Team ID = {{team.team_id}}</p>
</div>
The variable getStandings is taken from an API via an $http call. Like so:
In StandingsService
return $http.get(
'http://api.com/standings/1005?Authorization=xxxx'
)
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
And then StandingsService is attached to the getStandings variable in my controller.
"1005" is a property which calls a specific array, in this case a particular sporting competition, from an array of competitions.
So, on my index page I'm using ng-repeat to list all teams within that competition.
As you can see on the html above, I have linked each team so that it dynamically generates a URL which appends the team_id to the end, which using $routeParams I define as the variable whichTeam.
Team Details Page
<h1>Dynamic Team ID = {{whichTeam}}</h1>
This works fine, the team ID is generated dynamically according the team that is clicked.
Just like 'StandingsService' above, I have another service called 'TeamService' which makes an $http request to pull team data. Currently though it is set up statically to make a call to one individual team - I want to make the service take in the whichTeam variable so that the call changes depending on which team was clicked.
This is the static team $http request (I've broken the URL apart and concatenated to make it clearer):
return $http.get(
'http://api.com/team/' + '16110' + '?Authorization=xxxx'
)
I want the 16110 part, which refers to ONE team, to be a the whichTeam variable, allowing it to pull in the correct individual team data, but I don't know how to write this (or indeed if it's possible).
I hope I've been clear - happy to clarify further if needed. Thanks in advance.
Make a factory:
app.factory("DataService", ["$http", function($http) {
return {
getTeamDetailsById: function(teamId) {
return $http.get('path/to/api' + teamId + '?Auth=xxxx')
}
};
}]);
Use it in a controller:
app.controller("MainCtrl", ["$scope", "DataService", function($scope, DataService) {
$scope.teamDetails = {};
$scope.getTeamDetailsById = function(event, teamId) {
//prevent click navigation
event.preventDefault();
//call factory service
DataService.getTeamDetailsById(teamId).then(function(response) {
//success callback
$scope.teamDetails = response.data;
}, function(response) {
//an error has occurred
});
}
}]);
In the ng-repeat element:
<div ng-repeat="team in teams">
<a href ng-click="getTeamDetailsById($event, team.team_id)">{{team.team_name}}</a>
</div>
The above assumes you have only one state and are storing in only one controller. If you want to use different states usving $stateProvider, then you'd have to use parameters, by making use of ui-sref and passing in team Id.
If indeed you are using $states and parameters, do this:
<a href ng-click="goToState($event, team.team_id)">{{ team.team_name }}</a>
$scope.goToState = function(e, teamId) {
$state.go("teamDetailsState", { "teamId": teamId });
}

How can I include an angular module in an existing module?

So I've defined a custom section in Umbraco 7:
namespace NZ_Realty_Ltd.CRM
{
[Application("crm", "CRM", "trayuser", 8)]
public class CrmSection : IApplication { }
}
It shows up, no worries here. But it needs a view and controller. So I made a start on the controller:
angular.module("umbraco").controller("CrmController",
function ($scope, $http) {
$http.get('backoffice/crm/ContactApi/GetAll').success(function (data) {
$scope.contacts = data;
});
});
Again, no problem. My data is being read from a C# CRUD api and being sent back to the view. But I want to paginate these results. So I'm trying to use this custom directive to do it: https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Here's my html view:
<div ng-controller="CrmController">
<umb-pane>
<p>Page {{currentPage}} / {{totalPages}}</p>
<p>Showing {{pageSize}} items per page:</p>
<ul class="contacts">
<li dir-paginate="contact in contacts | itemsPerPage: 10">
<span>{{contact.name}}</span>
<p>{{contact.bio}}</p>
</li>
</ul>
<dir-pagination-controls></dir-pagination-controls>
</umb-pane>
</div>
The problem is none of these expressions are showing up (they are all blank). I've missed the step of how to include the pagination module. Actually I've been stuck on it for hours. I've tried everything from:
angular.module("umbraco", ['angularUtils.directives.dirPagination']).controller("CrmController",
function ($scope, $http) {
$http.get('backoffice/crm/ContactApi/GetAll').success(function (data) {
$scope.contacts = data;
});
});
... To just including the directive javascript file from <script> tags. But I really have no idea what I'm doing and don't understand the module syntax well enough (I've read through the pagination demo so many times but it just seems SO different to working with the umbraco angularjs app). I saw in the docs that including the second parameter means you're making a new module. But what is the relevance of the information inside the [] on the second parameter? And why would I be creating a new module? Can't I just include the existing directive?
EDIT: This is the closest in my mind to what should work. But I get no contacts listed and no pagination controls showing. My idea with it is to load the pagination module (and thus directive), and then create my controller as normal to avoid conflicts and load order stuff, but also adding default values in the controller as in the example here: http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview
angular.module("angularUtils.directives.dirPagination");
angular.module("umbraco").controller("CrmController",
function ($scope, $http) {
$http.get('backoffice/crm/ContactApi/GetAll').success(function (data) {
$scope.contacts = data;
$scope.currentPage = 1;
$scope.pageSize = 10;
});
});
You could add this before your controller starts:
app.requires.push('angularUtils.directives.dirPagination');
Read more at:
https://our.umbraco.org/forum/umbraco-7/developing-umbraco-7-packages/47905-Including-an-angular-module

Angularjs Reinitializing active controller

Is there a way to reinitialize a controller that is currently active ?
This would help me with transitioning from page to page without adding much additional workaround code.
For example:
<div ng-controller='Blah as ex'>
{{ex.name}}
</div>
and in the controller Blah's initialization function, the name would be retrieved from a service:
this.name = someService.name;
So for the example above, I'd like to have a button which would reinitialize my Blah controller.
edit: This is only a basic example.
I'm using the browser's 'state' in order to restore 'back' and 'forward' data in my controllers.
There are a few cases so I'm trying to simplify its process (which currently works, but is not as 'pretty')
Would something like this be a possible solution? Using route.reload to reload your page?
myapp.Controller('SampleController', function($location, $route) {
$scope.navTo = function(url) {
if ($location.path() === url) {
$route.reload();
} else {
$location.path(url);
}
}
});

View updates everywhere but in current controller - angularJS

EDIT: As asked, I'll explain a bit more efficiently !
I've been sitting in front of an annoying problem recently, which is that whenever I update a value inside a directive, the controllers I'm not currently "in" are the only ones to be updated properly.
Scenario example: Profile page is made of two controllers. Navbar_controller which is just currently displaying the user name :
<div ng-if="Auth.isAuthenticated">Hello, {{Auth.getCurrentUser().name}}</div>
The second controller , Profile_controller is here to update user values. This is a simple function in the angular first controller, which updates CurrentUser:
$scope.updateUser = function (type, form) {
if (!$scope.modif)
return ;
$http.put('/api/users/' + Auth.getCurrentUser()._id + '/update', {type:type, modif:$scope.modif})
.success(function (data, status) {
$scope.user = Auth.setNewUser(data);
})
.error(function () {
console.log("error");
});
};
When I update, for example, the name. I can see that the database has been modified properly. And indeed, navbar_controller got the update because a new name is printed in the div. However, Profile_controller doesn't get the update: the name printed in the profile page didn't change.
Here are the two basic functions in Auth.service.js :
getCurrentUser: function() {
return currentUser;
},
// 'user' is the data retrieved in http put request dot success
setNewUser: function(user) {
currentUser = user;
$rootScope.$broadcast(); // Navbar_controller is updated with or without this line
return currentUser;
}
Anyway, if I look at the navbar and its controller, which is calling Auth.getCurrentUser() method, the user values are instantly modified. I'e been using an ugly method consisting in modifying the controller values manually or by refreshing the page... But this isn't the way to go, right ?
There must be something with "$rootScope.$broadcast();", but I'm really new to Angular and other questions on stackoverflow are too specific to help me understand properly.
Thank you !
Your question was a little difficult to understand, but I think the problem is that you are reference a changing object in your various controllers. Here is an example to explain:
Service:
var myObject = { ... };
return {
getObject() { return myObject; }
setObject(obj) { myObject = obj; }
};
Controller 1:
$scope.myObjA = Service.getObject();
Controller 2:
$scope.myObjB = Service.getObject();
Now on initialisation both controllers will be referencing the same object, so if you changed a property inside either controller (eg. $scope.myObjB.name = 'bob';), then the other controller would also see the name.
However if you changed the object itself in a controller (eg. Service.setObject(newObj);), then the controller will be referencing the new object, while the other controller will still be referencing the old one.
You can fix this by wrapping your service object in a container:
var cont = {
user: ...
};
function getContainer() { return cont; }
function setNewUser(user) { cont.user = user; }
Then inside your controllers, get the container (not the user):
$scope.cont = Service.getContainer();
And inside your html:
<div>{{cont.user.name}}</div>
Now when you update the user, all attached controllers will be updated.
Well I'd try to change and store the user information in $rootScope, for your scenario could be a good fit.
getCurrentUser: function() {
$rootScope.currentUser===undefined ? 'no User': $rootScope.currentUser;
},
setNewUser: function(user) {
$rootScope.currentUser = user;
//$rootScope.$broadcast(); no need to broadcast
return getCurrentUser();
}
in that way currentUser will be updated in different scopes as needed!
I'll quote AnuglarJs FAQ regarding to $rootscope:
$rootScope exists, but it can be used for evil
Occasionally there are pieces of data that you want to make global to
the whole app. For these, you can inject $rootScope and set values on
it like any other scope. Since the scopes inherit from the root scope,
these values will be available to the expressions attached to
directives like ng-show just like values on your local $scope.
Of course, global state sucks and you should use $rootScope sparingly,
like you would (hopefully) use with global variables in any language.
In particular, don't use it for code, only data. If you're tempted to
put a function on $rootScope, it's almost always better to put it in a
service that can be injected where it's needed, and more easily
tested.
Conversely, don't create a service whose only purpose in life is to
store and return bits of data.

Resources