UI Router nested views - javascript

I've tried with various anwsers without any luck.
I have this two ui-views:
<div ui-view class="expand"></div> //Inside index.html
<div ui-view></div> //Inside home.html
And this is my routing:
$stateProvider
.state('home', {
url: '/',
views: {
'#': {
templateUrl: 'app/components/home/home.html',
controller: 'HomeCtrl'
}
}
})
.state('clients', {
url: '/clients',
views: {
'#home': {
templateUrl: 'app/components/clients/clients.html',
controller: 'ClientsCtrl'
}
}
})
I've tried putting names on the view and calling them in different ways but clients.html never gets display even though the route url changes.

I'm not entirely familiar with the view syntax that you're using with $stateProvider. I'll give you two versions, the first will seem very similar to your example and the second is more aligned with best practices.
$stateProvider
.state('base', {
abstract: true,
url: '',
templateUrl: 'views/base.html'
})
.state('login', {
url: '/login',
parent: 'base',
templateUrl: 'views/login.html',
controller: 'LoginCtrl'
})
.state('dashboard', {
url: '/dashboard',
parent: 'base',
templateUrl: 'views/dashboard.html'
})
Best practice version:
(function () {
'use strict';
angular
.module('app.core')
.config(stateConfig)
.run(errorHandler);
stateConfig.$inject = ['$stateProvider', '$urlRouterProvider', '$locationProvider'];
getZipCodes.$inject = ['googleMapService'];
errorHandler.$inject = ['$rootScope', 'logger'];
function stateConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider.state('core', {
url: '/',
templateUrl: 'app/core/core.html',
controller: 'CoreController',
controllerAs: 'vm',
resolve: {
getZipCodes : getZipCodes
}
})
}
/** #desc: Ping the back-end for a JSON object that will be converted into an array of NYC zip codes */
function getZipCodes(googleMapService) {
return googleMapService.getZipCodes();
}
/** #desc: $stateChangeError handler */
function errorHandler($rootScope, logger) {
$rootScope.$on('$stateChangeError', function (error, event) {
if (error) { logger.error('Error while changing states', error); }
if (event) { logger.error('The event that caused the error', event); }
})
}
})();

Related

Makes 2 states share a part of resolve

I have defined two states as follows:
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('edit', {
url: '/edit/{id}',
templateUrl: '/htmls/h1.html',
controller: 'SameCtrl',
onEnter: ...sameOnEnter...
resolve: {
...commonResolve...
}
})
.state('addinEdit', {
url: '/addin/edit/{id}',
templateUrl: '/htmls/h2.html',
controller: 'SameCtrl',
onEnter: ...sameOnEnter...
resolve: {
special: [ ... ],
...commonResolve...
}
})
}])
So they share the same controller, the same onEnter, and they have a very long and common part for resolve (which is actually a chain of resolves: first: function (...){...}, second: function (...){...}, ...). Does anyone know how to rewrite them so that I don't have to write commonResolve twice?
Just create a function for the resolver:
app.config(['$stateProvider', function ($stateProvider) {
resolverFunction.$inject = ['resolverA', 'resolverB'];
function ResolverFunction(myService1, myService2) {
return 'something';
}
resolverAFunction.$inject = ['resolverC'];
function resolverAFunction(resolverC) {
return 'anything';
}
resolverBFunction.$inject = ['resolverC'];
function resolverBFunction(resolverC) {
return 'something else';
}
resolverCFunction.$inject = ['service'];
function resolverCFunction(service) {
return 'something else';
}
$stateProvider
.state('edit', {
url: '/edit/{id}',
templateUrl: '/htmls/h1.html',
controller: 'SameCtrl',
onEnter: ...sameOnEnter...
resolve: {
commonResolver: resolverFunction,
resolverA: resolverAFunction,
resolverB: resolverBFunction,
resolverC: resolverCFunction,
}
})
.state('addinEdit', {
url: '/addin/edit/{id}',
templateUrl: '/htmls/h2.html',
controller: 'SameCtrl',
onEnter: ...sameOnEnter...
resolve: {
special: [ ... ],
commonResolver: resolverFunction,
resolverA: resolverAFunction,
resolverB: resolverBFunction,
resolverC: resolverCFunction,
}
})
}])
I don't have experience angularjs but i found a solution,
you can specify the parent of a state via the parent property.
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('edit', {
url: '/edit/{id}',
templateUrl: '/htmls/h1.html',
controller: 'SameCtrl',
onEnter: ...sameOnEnter...
resolve: {
...commonResolve...
}
})
.state('addinEdit', {
url: '/addin/edit/{id}',
templateUrl: '/htmls/h2.html',
parent : 'edit'
})
}])

how to change ionic ion-nav-view

Im writing a mobile app using Ionic framework, it has two languages: English and Spanish, I want to be able to switch the nav-view (as a template), to show in English or Spanish depending on the user selection language.
I'm trying to do this on my StateProvider definition, here is part of my code:
(function(){
'use strict';
angular
.module('app.core')
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/auth/login/login.html',
controller: 'LoginCtrl',
})
.state('loginEs', {
url: '/loginEs',
templateUrl: 'app/auth/login/loginEs.html',
controller: 'LoginCtrl',
})
.state('tabs', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabsEs', {
url: '/tabEs',
abstract: true,
templateUrl: 'templates/tabsEs.html'
})
.state('tabs.dashboard', {
url: '/dashboard',
views: {
'tab-dash': {
templateUrl: 'app/dashboard.html',
//controller: 'SignupCtrl',
}
}
})
.state('tabsEs.dashboardEs', {
url: '/dashboard',
views: {
'tabEs-dash': {
templateUrl: 'app/dashboardEs.html',
//controller: 'SignupCtrl',
}
}
})
.state('tabs.adults', {
url: '/adults',
views: {
'tab-dash': {
templateUrl: 'templates/tab-adults.html',
//controller: 'DashCtrl'
}
}
})
.state('tabs.adultsEs', {
url: '/adultsEs',
views: {
'tab-dash': {
templateUrl: 'templates/tab-adultsEs.html',
controller: 'customersCtrl'
}
}
})
.state('passwordResetForm', {
url: '/passwordResetForm',
templateUrl: 'app/auth/login/passwordResetForm.html',
controller: 'PasswordResetCtrl',
});
$urlRouterProvider.otherwise('login');
}]);
})();
When the state is tabsEs.dashboardEs it display correctly my navbar in spanish from templates/tabsEs.html. But I have been struggling some days to do the same when state change to tabs.adultsEs, but is not working, allways shown templates/tabs.html (english).
Does anybody see the error, or give me a tip to do this?
Regards,
Victor
DonĀ“t duplicate your templates, use a plugin like angular-translate to add internationalization to your app. Explore the docs, it's really simple.

angularjs - backspace is not working

I have a problem when i click on backspace
it doesn't go to the last page
i don't know how to fix it sometime it does go the last page only when i go from app.home page to app.newJob.Step1 and press backspace it goes back to home but not always
here is my router
'use strict';
angular.module('ijob').
config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'Views/login.html',
data: {
requireLogin: false
}
})
.state('app', {
abstract: true,
template: '<ui-view/>',
data: {
requireLogin: true
}
})
.state('app.home', {
url: '/home',
templateUrl: '/Views/home.html'
})
.state('app.editJob', {
url: '/editJob',
templateUrl: 'Views/editJob.html'
})
.state('app.purchasePackages', {
url: '/purchasePackages',
templateUrl: 'Views/purchasePackages.html'
})
.state('app.accountDetails', {
url: '/accountDetails',
templateUrl: 'Views/accountDetails.html'
})
.state('app.jobOrder2', {
url: '/jobOrder2',
templateUrl: 'Views/jobOrder2.html'
})
.state('app.newJob', {
abstract: true,
templateUrl: 'Views/newJob/newJob.html',
url: '/newJob'
})
.state('app.newJob.Step1', {
url: '/newJob/step1',
templateUrl: 'Views/newJob/step1.html'
})
.state('app.newJob.Step2', {
url: '/newJob/step2',
templateUrl: 'Views/newJob/step2.html'
})
.state('app.newJob.Step3', {
url: '/newJob/step3',
templateUrl: 'Views/newJob/step3.html'
})
.state('app.newJob.Step4', {
url: '/newJob/step4',
templateUrl: 'Views/newJob/step4.html'
})
.state('app.newJob.Step5', {
url: '/newJob/step5',
templateUrl: 'Views/newJob/step5.html'
});
$urlRouterProvider.otherwise('/home');
// $locationProvider.html5Mode(true);
})
.config(function config() {
});
and my app
'use strict';
// Declare app level module which depends on views, and components
angular.module('ijob', [
'ui.router', 'ngRoute', 'btorfs.multiselect', 'ngCookies', 'ngResource'
]);
var app = angular.module('ijob');
app.run(['$state', '$cookieStore', '$rootScope', 'Auth', 'UserService',
function ($state, $cookieStore, $rootScope, auth, userService) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var requireLogin = toState.data.requireLogin;
if (requireLogin && !($cookieStore.get('authdata'))) {
event.preventDefault();
$state.go('login');
}
else if ($cookieStore.get('authdata') && $state.current.name !== toState.name) {
userService.token = auth.getCredentials($cookieStore.get('authdata'));
console.log(userService);
$state.current.name = toState.name;
$state.go(toState.name);
}
});
}]);
sometimes i get that error
Error: No such state 'app.newJob.Step1'
or
Error: No such state 'login'
and the states do exist.
its something about the ui router?
or there is anyway to override that?

How to config Angular ui-router to not use strict URL matching mode

ui-router's version 0.2.11 introduced option to turn off strict URL matching, but I can't figure out how to actually use it.
I've tried standard config as they use in tests:
app.config(function ($urlMatcherFactoryProvider) {
$urlMatcherFactoryProvider.caseInsensitive(true);
$urlMatcherFactoryProvider.strictMode(false);
});
None of those settings work, so I guess I'm either doing something wrong or it's bugged. There's also seem to be no documentation about it.
I believe this was fixed in 0.2.12.
That said, I ran into this problem in 0.2.15. It turns out that you need to configure the $urlMatcherFactoryProvider BEFORE the $stateProvider.
i.e. the following code will NOT work:
$stateProvider.state('login', {
url: "/login",
templateUrl: 'templates/login.html',
controller: 'loginController as loginCtrl'
});
$urlMatcherFactoryProvider.caseInsensitive(true);
$urlMatcherFactoryProvider.strictMode(false);
You have to configure the $urlMatcherFactoryProvider first, like this:
$urlMatcherFactoryProvider.caseInsensitive(true);
$urlMatcherFactoryProvider.strictMode(false);
$stateProvider.state('login', {
url: "/login",
templateUrl: 'templates/login.html',
controller: 'loginController as loginCtrl'
});
use like this
app.config(["$routeProvider", "$locationProvider",
function ($routeProvider, $locationProvider) {
return $routeProvider.when("/", {
redirectTo: "/signin"
})
.when("/dashboard", {
templateUrl: "App/views/Dashboard/dashboard.html",
}).when("/signup", {
templateUrl: "App/views/signup/signup.html",
resolve: {
permission: function (authorizationService, $route) {
return authorizationService.permissionCheck("signup");
},
}
})
.when("/myAccount", {
templateUrl: "App/views/myAccount/myAccount.html",
resolve: {
permission: function (authorizationService, $route) {
return authorizationService.permissionCheck("myAccount");
},
}
})
.when("/signin", {
templateUrl: "App/views/signin/signin.html",
resolve: {
permission: function (authorizationService, $route) {
return authorizationService.permissionCheck("SKIP");
},
}
})

Angularjs organising/structuring states

I have over 100 pages. All pages use a different templates.
Currently, I have a long list of .state('page.html').state('page2.html') etc.
After 10-15 pages, I think this becomes unreadable/hard to manage.
Is there an easier/better way of organising states?
Javascript:
angular.module('app', ['ionic', 'ngCordova', 'app.controllers', 'app.directives', 'app.services', 'app.factories'])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.hide();
}
if (typeof navigator.splashscreen !== 'undefined') {
// org.apache.cordova.statusbar required
navigator.splashscreen.hide();
}
});
})
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/main.html',
controller: 'AppCtrl'
})
.state('app.home', {
url: '/home',
views: {
'menuContent': {
templateUrl: 'templates/pages/home.html',
controller: 'PageCtrl'
}
}
})
.state('app.page2', {
url: '/page2',
views: {
'menuContent': {
templateUrl: 'templates/pages/page2.html',
controller: 'PageCtrl'
}
}
})
//100 .state('page.html')
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/home');
});
You can organize your pages into different modules and add states specific to the module in the corresponding module's config. Also I suggest you to use ui-router which supports nested states and many other features.
For example:
angular.module('myapp.appointments', ['ui.router', 'myapp'])
.config(['$stateProvider', function ($stateProvider) {
var templatePath = ROOT_PATH + 'scripts/modules/appointments/views/';
$stateProvider
.state('appointments', {
url: '/appointments',
abstract: true,
views: {
"containerView": {
template: '<div ui-view></div>'
}
}
})
.state('appointments.list', {
url: '/list',
controller: "AppointmentsListCtrl",
templateUrl: templatePath + '/appointments-list.html'
})
.state('appointments.add', {
url: '/add/:fromPopup',
controller: "AppointmentsAddCtrl",
templateUrl: templatePath + '/add-appointment.html'
})
}]);
angular.module('myapp.customers', ['ui.router', 'myapp'])
.config(['$stateProvider', function ($stateProvider) {
var templatePath = ROOT_PATH + 'scripts/modules/customers/views/';
$stateProvider
.state('customers', {
url: '/customers',
abstract: true,
views: {
"containerView": {
templateUrl: templatePath + '/index.html'
}
}
})
.state('customers.list', {
url: '/',
controller: "CustomersListCtrl",
templateUrl: templatePath + '/list.html'
});
}]);
and you can have your main app's config containing some common states such as
angular.module('myapp', ['ui.router', 'myapp.appointments', 'myapp.customers'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('home', {
url: '/',
views: {
"containerView": {
controller: "DashboardCtrl",
templateUrl: ROOT_PATH + 'scripts/modules/dashboard/views/dashboard.html'
}
}
})
.state('404', {
url: '/404',
views: {
"containerView": {
templateUrl: ROOT_PATH + 'scripts/modules/common/views/404.html'
}
}
});
}]);
Instead of adding al these states, isn't it a better idea to dynamicly add the template based on a variable?
You might be looking for dynamic template name based on the state params
$stateProvider.state('app.page', {
templateUrl: function ($stateParams){
return 'templates/pages/page/' + $stateParams.pageid+ '.html';
}
})
Found this answer in:
ui-router dynamic template path

Categories