I am trying open uibmodal in angular but the parent state must change as per request of previous state.
My code of state.js -
(function() {
'use strict';
angular
.module('myApp')
.config(stateConfig);
stateConfig.$inject = ['$stateProvider'];
function stateConfig($stateProvider) {
$stateProvider
.state('save', {
parent: 'app',
url: '/save',
onEnter: ['$stateParams', '$state', '$uibModal', function($stateParams, $state, $uibModal) {
$uibModal.open({
templateUrl: 'app/save.html',
controller: 'SaveController',
controllerAs: 'vm',
backdrop: 'static',
size: 'lg'
});
}]
});
}
})();
Controller code looks like this -
(function() {
'use strict';
angular
.module('myApp')
.controller('SaveController', SaveController);
SaveController.$inject = ['$uibModalInstance','$state', '$scope','$stateParams' ];
function SaveController($uibModalInstance, $state, $scope, $stateParams) {
var vm = this;
var id = $state.params.id;
}
})();
I am trying to redirect to that state from parent state controller using:
$state.go("save",{id: 2, name:'test'});
I want to change parent state value as per request via controller, please suggest any possible solution for that.
It looks like you are just missing the root part:
$state.go("app.save",{id: 2, name:'test'});
this is the doc: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#stategoto--toparams--options
Related
I have just created a simple app. Route for main controller is working but not for another one.
This is the part of the code of route file
$routeProvider
.when('/', {
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.when('/signatures', {
templateUrl: 'app/components/signature/signature.html',
controller: 'SignatureController',
controllerAs: 'signature',
resolve: {
signatureLists: function(SignatureService){
return SignatureService.getSignatures();
}
}
})
.otherwise({
redirectTo: '/'
});
and below is the controller
(function() {
'use strict';
angular
.module('demoapp')
.controller('SignatureController', SignatureController);
/** #ngInject */
function SignatureController(signatureLists) {
var vm = this;
vm.signatures = signatureLists;
}
})
I have defined the module in another file:
(function() {
'use strict';
angular
.module('demoapp', ['ngRoute', 'toastr']);
})();
when I try to visit /signatures page, I get this error:
Error: [ng:areq] Argument 'SignatureController' is not a function, got undefined
Maybe its just a silly error due to a typo or something else but still I can't figure it out
You forgot to self invoke the controller closure..do a () at the end
(function() {
'use strict';
angular
.module('demoapp')
.controller('SignatureController', SignatureController);
/** #ngInject */
function SignatureController(signatureLists) {
var vm = this;
vm.signatures = signatureLists;
}
})()
I am working with IONIC Framework (Angularjs)
I am receiving below error,
463788 error Error: [ng:areq] http://errors.angularjs.org/1.4.3/ng/areq?p0=PaymentCtrl&p1=not%20a%20function%2C%20got%20undefined
at Error (native)
at http://localhost:8100/lib/ionic/js/angular/angular.min.js:6:416
at Sb (http://localhost:8100/lib/ionic/js/angular/angular.min.js:22:18)
at Qa (http://localhost:8100/lib/ionic/js/angular/angular.min.js:22:105)
at http://localhost:8100/lib/ionic/js/angular/angular.min.js:79:497
at I.appendViewElement (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:4463)
at Object.O.render (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:16:17590)
at Object.O.init (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:16:16825)
at I.render (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:3419)
at I.register (http://localhost:8100/lib/ionic/js/ionic-angular.min.js:17:3150)
Here is my code for controller.
define(['ionic', 'ionicAngular', 'angular',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular) {
'use strict';
console.log('Payment controller ');
var PaymentCtrl = function ($scope, PaymentSvc,$state, $ionicLoading) {
/*$scope.phoneNumberVerification = function() { $state,$ionicPopup,
console.log('PhoneNumber controller added1 ');
$ionicLoading.hide();
$state.go('tab.eateries');
};*/
// When button is clicked, the popup will be shown...
};
return PaymentCtrl;
});
Serveics.js
define(['ionic', 'ionicAngular', 'angular',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular) {
'use strict';
//console.log('service modules');
var PaymentSvc = function(){
console.log('serverices call');//var svc = this;
}
return PaymentSvc;
});
// });*/
payment.js
define(['ionic', 'ionicAngular', 'angular',
'./modules/payment/controllers/paymentctrl',
'./modules/payment/services/services',
'ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter'],
function (ionic, ionicAngular, angular,
paymentCtrl,
paymentSvc) {
'use strict';
console.log('payment.js modules');
var payment = angular.module('payment', ['ionic'])
.controller('PaymentCtrl', paymentCtrl)
.service('PaymentSvc',paymentSvc);
return payment;
});
No need to inject ['angular','ngRoute', 'angularAnimate', 'angularSanitize', 'uiRouter']. Ionic automatically inject angular decencies when you inject ['ionic']
Just write your controller directly
angular.module('starter', ['ionic']).controller('PayCtrl',function ($scope,$state,$ionicLoading,PaymentSvc){
//starter is the app name come from ng-app="starter"
$ionicLoading.show();
$scope.phoneNumberVerification = function(){
console.log('PhoneNumber controller added1');
$ionicLoading.hide();
$state.go('tab.eateries');
};
});
I advise you to organize your javascript project files to in 3 files:
app.js which contains
angular.module('starter', ['ionic', 'starter.controllers','starter.services'])..config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
}).state('app.home', {
url: '/home',
views: {
'tab-home': {
templateUrl: 'templates/home.html',
controller : 'HomeCtrl'
}
}
});
$urlRouterProvider.otherwise('/app/home');
});
controller.js which contains your controllers
angular.module('starter.controllers', []).controller('AppCtrl', function('PayCtrl',function ($scope,$state,$ionicLoading,PaymentSvc){
$ionicLoading.show();
$scope.phoneNumberVerification = function(){
console.log('PhoneNumber controller added1');
$ionicLoading.hide();
$state.go('tab.eateries');
};
});
service.js which contains you connections to server
angular.module('starter.services', []).factory('PaymentSvc',function($http,$q){
});
it is an injection error. for example, if you inject ['a','b','c'] you must have it in your function in the same order and amount: function(a,b,c). in your case, you have more parameters in the injection than the parameters in your controller function.
I'm trying to refactor our current layout to add in a dynamic show/hide section above the header on our page. We are using Angularjs 1.4.2 with ui-router and currently we are using separate route files, although we have a main route. The main.html section of the screen, up to now, was the only section with the dynamic content. In order to get my new route working, I'm having to add it and main to each of the existing routes.
My question is, would a better design be something along this line of a single parent route to handle a resolve, with nested states for the dynamic main content and a new view for my new route and content? As the application grows, do you still continue to put the new routes into the parent route or is there a better way to organize it like we were doing with individual route files or a combination of both?
This is what I'm trying, but it's not working yet, as I'm getting a blank page, but the design for future growth with the application is what I'm trying to get right here:
(function () {
'use strict';
angular
.module('myApp')
.config(config);
config.$inject = ['$stateProvider'];
/* #ngInject */
function config($stateProvider) {
$stateProvider
.state('root', {
template: '<ui-view></ui-view>',
abstract: true,
resolve:{
myLoader: ['myLoader', function(myLoader){
// $http returns a promise for the url data
return myLoader.load();
}]
}
}
.state('main'), {
url: '/?param1¶m2¶m3¶m4',
templateUrl: 'app/routes/main/main.html',
controller: 'MainCtrl',
redirectTo: 'main'
})
$stateProvider
.state('basicsearch', {
url: '/basic-search',
templateUrl: 'app/routes/basicsearch/basicsearch.html',
controller: 'searchQuickCtrl'
})
$stateProvider
.state('advancedsearch', {
url: '/advaned-search',
templateUrl: 'app/routes/advancedsearch/advancedsearch.html',
controller: 'advancedSearchkCtrl'
})
$stateProvider
.state('anothersearch', {
url: '/another-search',
templateUrl: 'app/routes/anothersearch/anothersearch.html',
controller: 'anotherSearchCtrl'
})
.state('myChange', {
url: '/myChange?param5¶m6¶m7¶m8',
views: {
"myChangeView": {
templateUrl: '/app/routes/myChange/myChange.html',
controller: 'myChangeCtrl'
}
}
});
}
})();
Here is a basic layout of what we have:
I am not sure about the issue. But I created working plunker, to show you how we can use state nesting and resolve.
So this is our parent controller for root state and the factory used in resolve
.factory('myLoader', function(){
return {
load: function () {return [1,2] }
};
})
.controller('ParenCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {
$scope.myLoader = myLoader;
}])
.controller('MainCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('searchQuickCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('advancedSearchkCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('anotherSearchCtrl', ['$scope', function ($scope) {}])
Next, we will use controller for abstract root state, to assign result into scope:
.state('root', {
template: '<div ui-view></div>',
abstract: true,
controller: 'ParenCtrl',
resolve:{
myLoader: ['myLoader', function(myLoader){
// $http returns a promise for the url data
return myLoader.load();
}]
}
})
And all states will use that as their parent, and inherit the scope:
.state('main', {
parent: 'root',
url: '/?param1¶m2¶m3¶m4',
templateUrl: 'app/routes/main/main.html',
controller: 'MainCtrl',
//redirectTo: 'main'
})
.state('basicsearch', {
url: '/basic-search',
templateUrl: 'app/routes/basicsearch/basicsearch.html',
parent: 'root',
controller: 'searchQuickCtrl'
})
.state('advancedsearch', {
url: '/advaned-search',
templateUrl: 'app/routes/advancedsearch/advancedsearch.html',
parent: 'root',
controller: 'advancedSearchkCtrl'
})
.state('anothersearch', {
url: '/another-search',
parent: 'root',
templateUrl: 'app/routes/anothersearch/anothersearch.html',
controller: 'anotherSearchCtrl'
})
And properly use it inside of this view:
<div >
<h3>current state name: <var>{{$state.current.name}}</var></h3>
<h4>resolved in parent</h4>
<pre>{{myLoader | json }}</pre>
<h5>params</h5>
<pre>{{$stateParams | json}}</pre>
<h5>state</h5>
<pre>{{$state.current | json}}</pre>
</div>
while all these controller do not use that resolved value
.controller('MainCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('searchQuickCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('advancedSearchkCtrl', ['$scope', 'myLoader', function ($scope, myLoader) {}])
.controller('anotherSearchCtrl', ['$scope', function ($scope) {}])
So, each controller can be provided with stuff resolved in parent (as parameter). That is shown above. But also, becuase parent already used that and assigned that to some $scope variable... all is alraeady in place.
Also check:
Angularjs ui-router abstract state with resolve
How do I share $scope data between states in angularjs ui-router?
Using ui-router-extras Sticky State (Parallel States) and Deep State Redirect as per http://christopherthielen.github.io/ui-router-extras/#/sticky, I'm unable to transition to a state that was previously activated.
app.js
'use strict';
angular.module( 'StickyStateDemo', [
'ui.router',
'ct.ui.router.extras',
'StickyStateDemo.controllers'
])
.config(function($stateProvider, $stickyStateProvider, $urlRouterProvider) {
var states = [];
$stickyStateProvider.enableDebug(true);
states.push({name: 'contentview', url: '/',
views: {
'#': {controller: 'ContentViewCtrl', templateUrl: 'contentView.tpl.html'}
}});
states.push({name: 'contentview.small', url: 'small/{myId}',
views: {
'smallview#contentview': {controller: 'SmallViewCtrl', templateUrl: 'smallView.tpl.html'}},
deepStateRedirect: true, sticky: true
});
states.push({name: 'contentview.large', url: 'large/{myId}',
views: {
'largeview#contentview': {controller: 'LargeViewCtrl', templateUrl: 'largeView.tpl.html'}},
deepStateRedirect: true, sticky: true
});
angular.forEach(states, function(state) { $stateProvider.state(state); });
$urlRouterProvider.otherwise('/');
})
.run( function run ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
});
controllers.js
'use strict';
angular.module('StickyStateDemo.controllers', []);
angular.module('StickyStateDemo.controllers')
.controller('MainCtrl', function ($scope, $state) {
$scope.launchSmallView = function() {
$state.go('contentview.small', {myId: 1});
};
$scope.launchLargeView = function() {
$state.go('contentview.large', {myId: 1});
};
})
.controller('ContentViewCtrl', function ($scope) {
})
.controller('SmallViewCtrl', function ($scope) {
})
.controller('LargeViewCtrl', function ($scope) {
});
Plunker with the entire application: http://plnkr.co/edit/yvtoUle0ZUWkSOmjlCoQ?p=preview You can enter both states fine the first time, but trying to return to a previously activated state will fail.
I'm probably just missing something, but I've scoured the interwebs for examples and tried numerous variations, but everything I try results in this same behavior.
Turns out this is a bug in ui-router-extras: https://github.com/christopherthielen/ui-router-extras/issues/103. Reverting to ui-router v0.2.11 (and leaving ui-router-extras at v0.0.10) is a temporary fix.
UPDATE: This has since been fixed in ui-router-extras
While implementing a modal for dialog boxes I am getting Error: [ng:areq] Argument 'ModalInstanceCtrl' is not a function, got undefined. I have two controllers in the same .js file. The error shows up the name of the second controller.
ng-app is contained in main html file.
<div ng-app = "LoginApp">
<div ng-view>
<!-- partial will go here -->
</div>
</div>
Angular routes
var LoginApp = angular.module('LoginApp', ['ngResource', 'ngRoute', 'ui.bootstrap'])
LoginApp.config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {controller: LoginCtrl, templateUrl: '/js/templates/login.html'})
.otherwise({redirectTo: '/'})
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
})
LoginCtrl.js file
'use strict'
var LoginCtrl = ['$scope', '$modal', '$log', function($scope, $modal, $log) {
$scope.authenticate = function(){
var loginModal = $modal.open({
templateUrl: 'login-modal.html',
controller: 'ModalInstanceCtrl',
resolve: {
modalData: function () {
return {
user: {
name: '',
password: ''
}
};
}
}
});
loginModal.result.then(function (user) {
$log.info("My name is:" + user.name);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
}
}];
var ModalInstanceCtrl = ['$scope', '$modalInstance', 'modalData', function($scope, $modalInstance, modalData){
}];
In the LoginCtrl.js file, LoginCtrl doesn't shows up this error but the declaration of ModalInstanceCtrl is undefined. Could anyone let me know why is this happening.
In the param of $modal.open(), change from this:
...
controller: 'ModalInstanceCtrl',
...
To this:
...
controller: ModalInstanceCtrl,
...
Notice, no quotes for the name of the controller, because you want AngularJS to use the ModalInstanceCtrl variable, not a controller registered with angular.
Alternatively, if you want to keep the quotes, you can register ModalInstanceCtrl with AngularJS, like this:
LoginApp.controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'modalData', function($scope, $modalInstance, modalData){
...
}]);
Either way will work.