I have a form in angular, that submits to an API, that returns a 201 status code, and the id and token of the object that was created. My idea is to open up a modal, with that token and show it to the user.
The value of $scope.object.token is updated, but I can't update that state in the view. I tried, $scope.$apply() I get an error $digest already in progress when calling $scope.$apply(). I also tried $timeout() but it doesn't update the view.
controller that handles that behavior is:
angular.module('myApp').controller('ObjectCtrl', ['$scope', 'user', 'object', '$routeParams', '$location', '$uibModal',
function ($scope, user, object, $routeParams, $location, $uibModal, displayToken) {
$scope.object = {
user_id: user.currentUser
}
$scope.create_object = function() {
var promise = object.create($scope.object);
promise.then(function(data){
var token = data.data.token;
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: '/app/views/modal_submit_token.html',
controller: 'ObjectCtrl',
resolve: {
displayToken: function () {
$scope.object.token = token;
}
}
});
});
};
}]);
And on my html,
<p><b>{{ object.token }}</b></p>
To pass the parameter you need to use resolve and inject the items in controller
$scope.Edit = function (Id) {
var modalInstance = $modal.open({
templateUrl: '/app/views/admin/addeditphone.html',
controller: 'EditCtrl',
resolve: {
editId: function () {
return Id;
}
}
});
}
Now if you will use like this:
app.controller('EditCtrl', ['$scope', '$location'
, function ($scope, $location, editId)
in this case editId will be undefined. You need to inject it, like this:
app.controller('EditCtrl', ['$scope', '$location', 'editId'
, function ($scope, $location, editId)
Now it will work smooth, I face the same problem many time, once injected, everything start working!
Font: Pass parameter to modal
Related
Here is the thing. I am not able to pass data from angular modal back to the controller where i need it. the codes given below.
Controller side
'use strict'
var DataMod = angular.module('Data', ["angularGrid", 'ui.bootstrap.contextMenu', 'ui.bootstrap']);
DataMod.controller('DataController', ['$scope', '$compile', '$uibModal', '$log','$rootScope', '$http', function ($scope, $compile, $uibModal,$log, $rootScope, $http, ngUtilityService) {
//user first clicks on Add button. A modal opens up. ModalInstanceCtrl is the controller used.
$scope.adduser = function () {
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl
});
//response data should be available here.
};
var ModalInstanceCtrl = function ($scope, $uibModalInstance) {
//ajax call is made is inside this controller and i get a response.
//this response is an object. i need to pass this object back to the adduser function. mentioned it above.
};
}
]);
As you can see above, there is the main controller. I have used a modal inside there which has its own controller. I make ajax call inside that modals controller and get a response back.
I want that response as a result to be available back at the adduser function so that i can work with that data. However, it seems that once the adduser function starts, it goes to the ModalInstanceCtrl and ends its execution there. It doesnt come back to the adduser function at all. I need a way to get back to the adduser function.
Can anyone let me know how to achieve this. Also how to pass the object response from ModalInstanceCtrl to the main controller inside adduser function.
It looks like you are using the Angular Bootstrap Modal, yes? First, I would set it up so that the modal controller is separated out from the main controller. Second, you are missing the promise needed to pass the response from the modal to the main controller. You can read about the return modal instance in the docs here: https://angular-ui.github.io/bootstrap/#/modal
This is the example code from the Angular Bootstrap plunkr: http://plnkr.co/edit/nGjBtMp33pFDAQ6r7Tew?p=info
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $uibModal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.animationsEnabled = true;
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
});
// Please note that $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$uibModalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
I am trying to redirect a user to different page after user is authenticated. I am using jwt authentication and I tried with $location, $window for redirection but its throwing error $state.go is not a function. I am new to angular and I am guessing there should be way to redirect may using a service in angular but I am still new to factories and service.
I have my state provider like this in state.js file:
myApp.config(function ($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/Home");
var header = {
templateUrl: 'commonViews/Header.html',
controller: function ($scope) {
}
};
var footer = {
templateUrl: 'commonViews/Footer.html',
controller: function ($scope) {
}
};
// ui router states
$stateProvider
.state('Home', {
url: "/Home",
views: {
header: header,
content: {
templateUrl: 'views/HomePage.html',
controller: function ($scope) {
}
},
footer: footer
}
})
.state('LoggedIn', {
url: "/LoggedIn",
views: {
'header': header,
'content': {
templateUrl: 'views/LoggedIn.html',
controller: function () {
}
},
'footer': footer
}
});
});
and loginController.js:
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state)
{
$scope.email = "";
$scope.password = "";
$scope.token = "";
$scope.loginForm = function () {
var data = {email: $scope.email, password: $scope.password};
var url = 'rs/loginResource/login';
$http.post(url, data).then(function (response)
{
$localStorage.token = response.data.token;
console.log("Encoded Token in localstorage is:" + $localStorage.token);
if ($localStorage.token) {
// $location.url("/LoggedIn");
$state.go('/LoggedIn');
}
}, function (error)
{
console.log("error", error);
});
};
}]);
further I have to perform refresh token based on expiration time etc, so is it better to have separate the functions like using a service to do the signup and signin?
The problem is the definition of your controller and the way you're handling your injections. And no, referring to your own answer to your question, the problem is not the "order" of the injections. It's a bit worse.
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state)
in this code you're mapping '$scope' to a $scope variable, '$http' to $http, 'jwtHelper' to jwtHelper, '$localStorage' to $localStorage and '$state' to $sessionStorage, and you're not mapping anything to $state. So obviously you get an error when you try to call a method on an undefined $state variable.
So in short, you're injecting 5 dependencies and you're assigning 6 variables to your dependencies, which in turn results in things not doing what they're supposed to do.
You can use Angular $window:
$window.location.href = '/index.html';
$state. go accepts the view name, not the URL. Replace '/LoggedIn' with Logged and you should be good.
Use $state.go instead of $window and location.
Add $state injector on controller
write code $state.go('LoggedIn');
Instead $state.go('/LoggedIn');
Write state name('LoggedIn') instead of url('/LoggedIn').
Hopefully this will work in your case.
You need to add $window as a dependency to your controller if you are using $window,
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state','$window', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state,$window)
{
$window.location.href = '/index.html';
}
otherwise change the route like this, here also you need to inject $state,
myApp.controller('loginController', ['$scope', '$http', 'jwtHelper', '$localStorage', '$state','$window','$state', function ($scope, $http, jwtHelper, $localStorage, $sessionStorage, $state,$window,$state)
{
$state.go('LoggedIn');
}
I'm trying to modify standard user module of meanjs. I added a simple route:
state('users', {
url: '/users/:username',
templateUrl: 'modules/users/views/view-profile.client.view.html'
});
And in my view:
data-ng-controller="ViewProfileController" data-ng-init="findUser()"
I also injected $stateParams to my controller. So in my ViewProfileController - findUser function, when I write this:
console.log($stateParams.username)
I expect to get username parameter. But it returns undefined.
When I set the route this way,
state('users', {
url: '/users/:username',
template: function ($stateParams){
return $stateParams.username;
}
});
it returns username. I don't know what is wrong or missing. Any ideas?
edit: this was my full controller code
'use strict';
angular.module('users').controller('ViewProfileController', ['$scope', '$http', '$stateParams', '$location', 'Users', 'Authentication',
function($scope, $http, $location, Users, Authentication, $stateParams) {
$scope.user = Authentication.user;
$scope.findUser = function () {
console.log($stateParams);
...
};
}
]);
Your dependencies don't match up - the list of dependencies need to match the parameters in the controller function in the same order:
'use strict';
angular.module('users')
.controller('ViewProfileController', ['$scope', '$http', '$stateParams', '$location', 'Users', 'Authentication',
function($scope, $http, $stateParams, $location, Users, Authentication) {
$scope.user = Authentication.user;
$scope.findUser = function () {
console.log($stateParams);
};
}
]);
I should use controller instead of template.
Replace into you code the template: to the follow snippet:
controller: function($stateParams){
console.log('username: '+$stateParams.username);
}
You can see a complete example of this feature here
I set the $stateParam by getting a cell value from a table:
$scope.tableClick = function() {
var tr = $('#Table_1').find('tr');
var id = $(event.target).parent().find("td:first").text();
$stateParams.engineId == id;
$state.go('engineselection');
}
When I stop the debug at this point. It gives me the engineId value.
This is the router part that I use:
$stateProvider.state('engineselection', {
url : '/engineselection:engineId',
templateUrl : 'assets/views/engineselection.html',
controller : 'EngineSelectionCtrl'
})
This is what happens in the controller:
controllers.controller("EngineSelectionCtrl",
["$scope", "$rootScope", "directiveBinder", '$timeout', '$stateParams', '$resource', '$location', 'rtmService', '$state',
function($scope, $rootScope, directiveBinder, $timeout, $stateParams, $resource, $location, myService, $state) {
myService.loadViewWithEngine(function(id, data) {
$scope.views = data;
$scope.$apply();
$('#loadingViews').spin(false);
});
When I stop here before the function and type console $stateParams, it tells me that I have a state parameter named 'engineId' but it is undefined. What should I do to pass the parameter to the controller with its value?
Worked after I have changed $state.go call like this:
$state.go('viewselection', {engineProgramId: id});
I'm experimenting with $routeParams, by following along with this example in the AngularJS documentation. For reference, here is the script itself:
angular.module('ngRouteExample', ['ngRoute'])
.controller('MainController', function($scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
})
.controller('BookController', function($scope, $routeParams) {
$scope.name = "BookController";
$scope.params = $routeParams;
})
.controller('ChapterController', function($scope, $routeParams) {
$scope.name = "ChapterController";
$scope.params = $routeParams;
})
.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterController'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
What I can't understand is this: how does MainController get the updated $routeParam object? I can see that as I click, items that MainController is responsible for setting are changing, but I don't understand how. It's making it a little tough to reproduce this behavior.
It doesn't get re-instantiated, and it's not "getting" the updated $routeParams object - the object in the controller is the routeParams object. It is the same object that is in the other controllers, not a "copy" of it.
So when the $routeParams object gets changed, the other controller already has the changes.