I have a LanguageSwitcher service and a LanguageSwitcher.switchLanguage() function that I can use to switch Language between french and english.
I am now trying to use a ui-router state to execute that function and it seems to work because I can see a 'translated' class (it toggles between 'french' and 'english') change in the markup when inspecting BUT the page goes blank like it's trying to load a view that is not there or something.
So I would like to prevent this behaviour and simply execute the function 'without changing the state' if possible.
<a ui-sref="language">Toggle</a>
Here is the ui-router config:
'use strict';
(function() {
angular.module('frontApp')
.run(['$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}]
)
.config(['$urlRouterProvider', '$stateProvider', '$locationProvider', function($urlRouterProvider, $stateProvider, $locationProvider){
$urlRouterProvider
.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/home.html',
controller: 'HomeCtrl'
})
.state('home.rules', {
url: '^/rules',
templateUrl: '/views/rules.html'
})
.state('home.terms', {
url: '^/terms',
templateUrl: '/views/terms.html'
})
.state('home.faq', {
url: '^/faq',
templateUrl: '/views/faq.html'
})
.state('language', {
controller: ['LanguageSwitcher', function(LanguageSwitcher) {
LanguageSwitcher.switchLanguage();
}]
});
$locationProvider.html5Mode(true);
}]);
}());
This is because my menu is dynamic and the toggle is not the last item of the navbar:
<header ng-controller="NavbarCtrl">
<h1><a class="navbar-brand" ui-sref="home">{{ 'siteTitle' | translate }}</a></h1>
<ul class="nav navbar-nav navbar-right">
<li ng-repeat="item in menu" ui-sref-active="active">
<a ui-sref="{{item.state}}" ng-href="{{item.link}}">{{item.title}}</a>
</li>
</ul>
</header>
The navbar.js file:
'use strict';
(function() {
angular.module('frontApp').controller('NavbarCtrl', ['$scope', '$translate', '$location', '$rootScope', function ($scope, $translate, $location, $rootScope) {
$rootScope.$on('$translateChangeSuccess', function () {
$translate(['linkHome', 'linkRules', 'linkTerms', 'linkFAQ', 'language', 'otherLanguage', 'linkMainSite']).then(function (translations) {
$scope.menu = [
{
'title': translations.linkHome,
'link': '/',
'state': 'home'
},
{
'title': translations.linkRules,
'link': '/rules',
'state': 'home.rules'
},
{
'title': translations.linkTerms,
'link': '/terms',
'state': 'home.terms'
},
{
'title': translations.linkFAQ,
'link': '/faq',
'state': 'home.faq'
},
{
'title': translations.language,
'link': '/'+translations.otherLanguage,
'state': 'language'
},
//{
// 'title': translations.linkMainSite,
// 'link': 'http://'+translations.linkMainSite,
// 'state': ''
//}
];
//$scope.isActive = function(route) {
// return route === $location.path();
//};
});
});
}]);
}());
What I am missing? Many thanks for your time and help.
Based on the problem being how to use ng-repeat for the menu links, one suggestion would be using ng-if to create a different link for language that uses ng-click to manage the switching and not set any href attributes for it
Something like
<li ng-repeat="item in menu" ui-sref-active="active">
<a ng-if="item.state !== 'language'" ui-sref="{{item.state}}" ng-href="{{item.link}}">{{item.title}}</a>
<a ng-if="item.state === 'language'" ng-click="switchLang()">{{item.title}}</a>
</li>
Then in NavbarCtrl controller have switchLang() make the call to your language service
This is inferred in many of the comments from your post: there is no reason to use a state to call the language switcher.
Instead you probably just want to include the controller in your menu using ng-controller, or create a component/directive, and call the service method through the using ngClick.
Related
Here is my :
config.router.js
app.config(['$stateProvider', '$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$ocLazyLoadProvider', 'JS_REQUIRES',
function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide, $ocLazyLoadProvider, jsRequires) {
app.controller = $controllerProvider.register;
app.directive = $compileProvider.directive;
app.filter = $filterProvider.register;
app.factory = $provide.factory;
app.service = $provide.service;
app.constant = $provide.constant;
app.value = $provide.value;
// LAZY MODULES
$ocLazyLoadProvider.config({
debug: false,
events: true,
modules: jsRequires.modules
});
// APPLICATION ROUTES
// -----------------------------------
$urlRouterProvider.otherwise('/login/signin');
//
// Set up the states
$stateProvider.state('app', {
url: "/app",
templateUrl: "assets/views/app.html",
resolve: loadSequence('modernizr', 'moment', 'angularMoment', 'uiSwitch', 'perfect-scrollbar-plugin', 'toaster', 'ngAside', 'vAccordion', 'sweet-alert', 'chartjs', 'tc.chartjs', 'oitozero.ngSweetAlert', 'chatCtrl'),
abstract: true
}).state('app.dashboard', {
url: "/dashboard",
templateUrl: "assets/views/dashboard.html",
resolve: loadSequence('jquery-sparkline', 'dashboardCtrl'),
title: 'Dashboard',
ncyBreadcrumb: {
label: 'Dashboard'
}
})
...
loginCtrl.js
app.controller('LoginCtrl', ["$scope", "alert", "auth", "$state", "$auth", "$timeout", function ($scope, alert, auth, $state, $auth, $timeout) {
$scope.submit = function () {
$auth.login({
email: $scope.email,
password: $scope.password
})
.then(function(res) {
var message = 'Thanks for coming back ' + res.data.user.email + '!';
if (!res.data.user.active)
{$auth.logout();
message = 'Just a reminder, please activate your account soon :)';}
alert('success', 'Welcome', message);
return null;
})
.then(function() {
$timeout(function() {
$state.go('main');
});
})
.catch(handleError);
} // submit function for login view
function handleError(err) {
alert('warning', 'oops there is a problem!', err.message);
}
}]);
main.js
var app = angular.module('myApp', ['my-app']);
app.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
// Attach Fastclick for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers
FastClick.attach(document.body);
// Set some reference to access them from any scope
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
// GLOBAL APP SCOPE
// set below basic information
$rootScope.app = {
name: 'My App',
author: 'example author',
description: 'My Platform',
version: '1.0',
year: ((new Date()).getFullYear()),
isMobile: (function () {
var check = false;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
check = true;
};
return check;
})()
};
$rootScope.user = {
name: 'Peter',
job: 'ng-Dev'
};
}]);
the problem is when I add ng-controller="loginCtrl" to my login div on the html file for login, it works. But I have another div just below the login div:
<div class="copyright" >
{{app.year}} © {{ app.name }} by {{ app.author }}.
</div>
This doesn't work! however, I have a similar one above the login div, it works:
<div class="logo">
<img ng-src="{{app.layout.logo}}" alt="{{app.name}}"/>
</div>
where is the problem? How to address it?
thanks
if you are using angular ui-router, it's not neccessary to add ng-controller="loginCtrl" to your DIVs manually, instead add controller property in your $stateProvider.state
example:
.state('app.dashboard', {
url: "/dashboard",
templateUrl: "assets/views/dashboard.html",
title: 'Dashboard',
controller: 'dashboardCtrl',
resolve: {
deps: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('path/to/your/controller.js');
}]
},
ncyBreadcrumb: {
label: 'Dashboard'
}
})
when you change your state usually views change to, that's the point right? setting controllers on the fly might not work as you expect.
checkout documentation
I'm trying to lazy load a directive in my angular app, using ui.router and oc.lazyLoad. Here is my code :
menu :
<ul>
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="demo">Demo</a></li>
<li><a ui-sref="test">Test</a></li>
</ul>
<ui-view></ui-view>
route config :
angular.module('app', ['ui.router', 'oc.lazyLoad'])
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state("demo", {
url:'/demo',
views: {
'lazyLoadView' : {
template: '<demo-directive></demo-directive>'
}
},
resolve : {
loadDemoModule : ['$ocLazyLoad', function($ocLazyLoad) {
console.log('resolving demo lazy load');
return $ocLazyLoad.load('demo.js');
}]
}
})
.state("home", {
templateUrl : 'core/home.html',
url : '/home'
})
}])
and the directive :
angular.module('app').
directive('demoDirective', function() {
return {
restrict: 'E',
scope: {},
template: require('./demo-directive.html'),
// templateUrl: 'demo-directive.html',
controllerAs: 'demo',
controller : ['$timeout', function($timeout) {
console.log('in directive controller');
}]
};
});
I have no errors, the console.log in resolve function is displayed, the demo.js file is loaded but then noting is happening, console form directive controller is not displayed. I'm trying to follow the first example from ocLazyLoad example
Thanks
How about lazy loading this way.
return $ocLazyLoad.load({
name: 'app.demo',
files: ['path/to/demo.js']
})
You have not declared the oc.lazyLoad module as a dependency.
angular.module('app.demo', ["oc.lazyLoad"])
See the quickstart - https://oclazyload.readme.io/docs/
You're also not closing your demo directive
template: '<demo-directive></demo-directive>'
I am having an issue with ui router where the state is not being triggered on a url.
On navigation to /#/dashboard/ the $state.current is set to abstract true with no state selected within.
No error messages are being thrown on $stateChangeError
JS -
var app = angular.module('frame', ['ui.router']);
app.config(['$stateProvider', '$locationProvider', function($stateProvider, $locationProvider) {
$stateProvider
.state('dashboard', {
url: '/dashboard/',
views: {
'header#': {
template: 'header'
},
'nav#': {
template: 'nav'
},
'main#': {
template: 'main'
}
}
});
// $locationProvider.html5Mode(true);
}]).
run(['$browser', '$rootScope', '$state', function($browser, $rootScope, $state){
// $browser.baseHref = function() { return '../'; };
$rootScope.$on("$stateChangeError", console.log.bind(console));
console.log(window.location);
$rootScope.state = $state;
}]);
html -
<body>
<div ui-view="header">
</div>
<nav ui-view="nav">
</nav>
<main ui-view="main">
</main>
</body>
Here is a link that throughly explains how to use Absolute Names,
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
I'm struggling to make my category and vendor name visible on breadcrumbs.
I'm using ng-breadcrumbs module (https://github.com/ianwalter/ng-breadcrumbs).
I guess I have problem with making curCategory and curVendor globally acessible, but tried some ways and can't make it working.
Here is my html:
<body ng-controller="mainController as main">
(...)
<ol class="breadcrumb">
<li ng-repeat="breadcrumb in breadcrumbs.get({'Category':curCategory,'Vendor': curVendor}) track by breadcrumb.path" ng-class="{ active: $last }">
<a ng-if="!$last" ng-href="#{{ breadcrumb.path }}" ng-bind="breadcrumb.label" class="margin-right-xs"></a>
<span ng-if="$last" ng-bind="breadcrumb.label"></span>
</li>
</ol>
My routes:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/pages/main.html',
label: 'Home'
}).
when('/:cat', {
templateUrl: 'templates/pages/category.html',
label: 'Category'
}).
when('/:cat/:ven', {
templateUrl: 'templates/pages/vendor.html',
label: 'Vendor'
}).
otherwise({
redirectTo: '/'
});
}]);
My controller:
var app = angular.module("myApp", [
'ngRoute',
'ng-breadcrumbs'
]);
app.controller('mainController', function($scope, $routeParams, breadcrumbs) {
$scope.breadcrumbs = breadcrumbs;
$scope.curCategory = $routeParams.cat;
$scope.curVendor = $routeParams.ven;
(...)
});
Uff I found what was wrong!
What suprised me was that inside specific controllers it worked fine, but when I moved it to mainController it returned empty object from $routeParams.
Here is solution:
$scope.$on('$routeChangeSuccess', function() {
$scope.curCategory = $routeParams.cat;
$scope.curVendor = $routeParams.ven;
});
It just assigned variables before $routeParams were populated.
I am using angular-ui-router module of AngularJS and have the following ui-sref which when I hover over shows http://localhost:3000/u/bob#/123/pin/4567, but when I click on it, I get only http://localhost:3000/u/bob#/123/pin/ on the browser's URL address bar and get the parameter value 4567 lost.
HTML code (index.html):
<a ui-sref="users.maker">
<!-- stuff -->
</a>
JavaScript code:
.state('users', {
url: '/:foo',
views: {
'': {
templateUrl: '/partials/index.html',
controller: ['$rootScope', '$stateParams',
function($rootScope, $stateParams) {
//stuff
}]
}
}
})
.state('users.maker', {
url: '/pin/:bar',
templateUrl: '/partials/users.maker.html',
controller: ['$stateParams', '$scope', '$http',
function($stateParams, $scope, ) {
//stuff
}]
})
Could somebody help me with it?
Have you tried defining your ui-sref as following?
ui-sref="users.maker({ param })
Dynamic ui-sref do not work in ui-router. A function using $state.href() could be used to resolve this issue.
So <a ui-sref="users.maker({ foo: bar })">...</a> could be done by following:
HTML
<a href="{{goToState('users.maker', bar)}}">..<a>
Inside AngularJS Controller
$scope.goToState = function(state, param) {
return $state.href(state, {foo: param});
}
This is with angular-ui-router version 0.2.10.
For more:
https://github.com/angular-ui/ui-router/issues/395