Based on this tutorial, I have as my parent state a list of people. When I click on one of them, a new view is created in order to show the details for that person. In my URL I use the ID for that person, so it's rather easy to go and fetch the ID to be used in the child state. The problem is that I also want to pass information such as the name, e-mail, age, etc.
The code is as follows:
My routes:
angular
.module('appRoutes', ["ui.router"])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
var TalentForceState_seeProfile = {
name: 'students',
url: '/seeProfile',
templateUrl: 'public/templates/talentforce_template.html',
controller: 'People_Controller'
}
var singleStudent = {
name: 'student',
parent: 'students',
url: '/:personId',
templateUrl: 'public/templates/person_template.html',
controller: 'Person_Controller'
}
....
Then, the controller for People:
talentforceApp
.controller('People_Controller', ['$scope', '$state', '$stateParams', 'StudentService', function($scope, $state, $stateParams, StudentService) {
StudentService.query().$promise.then(function(data) {
$scope.students = data;
});
}]);
Then, the controller for Person:
talentforceApp
.controller('Person_Controller', ['$scope', '$state', '$stateParams', 'StudentService', function($scope, $state, $stateParams, StudentService) {
$scope.student_id = $stateParams.personId;
console.log($stateParams)
}]);
Also, here's the HTML for the Person:
A person!
Name: {{student_name}}
Id: {{student_id}}
Information such as student_name
is what I can't seem to pass from the parent state
I tried using solutions like this, that use $state.go
, or this, that use params
, but it always gives me errors such as param values not valid for state
or the variables are undefined.
Any solution for this problem?
Answer
You can use angular's state resolve
to achieve your requirement in a better way. Although there are many choices for it.
Procedure:
- When your parent state loads, you query all the people in an API call.
- In that response, I am assigning the response to an instance of a service using
studentService.addStudents($scope.students);
whereaddStudents
is a function in the service. - Now, when you navigate to the detail of a person, I have used resolve which fetches the stored data from the service using the function
studentService.getStudents()
and returns aperson
object to the controller. - Use that person object directly in the person controller by injecting the resolve variable
I prefer using resolve
. I will tell you why.
Here is the resolve you can use:
resolve: {
student: function(studentService, $stateParams) {
return studentService.getStudents().find(function(student) {
return student.id === $stateParams.personId;
});
}
}
You will add a service studentService
or you can extend your own service.
Service:
talentforceApp.service('studentService', function(){
vm = this;
vm.students = []
this.addStudents = function(students) {
vm.students = students;
}
this.getStudents = function() {
return vm.students;
}
});
I added addStudents
and getStudents
methods to it.
One method add students to array and the other get the data of a studenr.
People Controller revised:
talentforceApp
.controller('People_Controller', ['$scope', '$state', '$stateParams', 'StudentService', function($scope, $state, $stateParams, StudentService,studentService) {
StudentService.query().$promise.then(function(data) {
$scope.students = data;
studentService.addStudents($scope.students); // this will create a students array in service instance
});
}]);
I assigned $scope.students
to the service instance.
routes revised:
var TalentForceState_seeProfile = {
name: 'students',
url: '/seeProfile',
templateUrl: 'public/templates/talentforce_template.html',
controller: 'People_Controller'
}
var singleStudent = {
name: 'student',
parent: 'students',
url: '/:personId',
templateUrl: 'public/templates/person_template.html',
controller: 'Person_Controller',
resolve: {
student: function(studentService, $stateParams) {
return studentService.getStudents.find(function(student) {
return student.id === $stateParams.personId;
});
}
}
}
Now, you can use student
from resolve into your controller, as a dependency.
person controller revised:
talentforceApp
.controller('Person_Controller', ['$scope', '$state', '$stateParams', 'StudentService',student, function($scope, $state, $stateParams, StudentService,student) {
$scope.student_id = $stateParams.personId;
console.log($stateParams)
$scope.student = student // this line add student to scope
console.log($scope.student)
}]);
Check your student object in the view:
View:
A person!
{{student}}
Name: {{student_name}}
Id: {{student_id}}
here is why I prefer to use resolve and its advantages
No comments:
Post a Comment