I would to make something like this:
.state('tabs.order', {
url: "/order/:orderId",
views: {
'orders-tab': {
templateUrl: "templates/orderDetail.html",
controller: 'OrderDetailController'
},
'orders-all-tab': {
templateUrl: "templates/orderDetail.html",
controller: 'OrderDetailController'
}
}
})
then in my view i would to put a conditional ui-sref in which i can choose the tab to be addressed; something like this:
ui-sref="tabs.order({orderId:order.ID}, <orders-tab or orders-all-tab?>)"
would this be possible?
Thanks
Well, I don't think there is any way yet to specify the view in ui-sref, but here is a starting point which I hope it will help you..
Firstly, the routes:
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/order/all-orders");
$stateProvider
.state("order", { abtract: true, url:"/order", templateUrl:"main.html" })
.state("order.orderTab", { url: "/order-details", templateUrl: "orderDetails.html" })
.state("order.orderAllTab", { url: "/all-orders", templateUrl: "allOrders.html" });
});
Then, define your main page (Orders and Order Details) [main.html]
<div ng-controller="mainController">
<tabset>
<tab
ng-repeat="t in tabs"
heading="{{t.heading}}"
select="go(t.route)"
active="t.active">
</tab>
</tabset>
<h2>View:</h2>
<div ui-view></div>
</div>
And the page controller to specify the tab data:
app.controller("mainController", function($rootScope, $scope, $state) {
$scope.go = function(route){
$state.go(route);
};
$scope.active = function(route){
return $state.is(route);
};
$scope.tabs = [
{ heading: "Order", route:"order.orderTab", active:true },
{ heading: "All Orders", route:"order.orderAllTab", active:false },
];
$scope.$on("$stateChangeSuccess", function() {
$scope.tabs.forEach(function(tab) {
tab.active = $scope.active(tab.route);
});
});
});
All you have to do next is to include the orderID.
Here is a demo
Related
I am trying to add viewTitle to base view or root web app page, e.g.
Root Page
<div ng-app="app">
{{viewTitle}}
<div ui-view=""></div>
</div>
can I change viewTitle in controllers ?
Controller-1
var myApp = angular.module(app, []);
myApp.controller('ChildController', ['$scope', function($scope) {
// how to update viewTitle here ?
}]);
One solution may be this:
If you use ui-router you can add a title in state: (I use this to translate the title)
.state('login', {
url: '/login',
controller: 'AdminLoginController',
templateUrl: 'app/admin/views/login.html',
title: {
'es': 'Iniciar sesión',
'en': 'Login',
'de': 'Einloggen'
}
})
.state('panelAdmin', {
url: '',
controller: 'AdminHomeController',
templateUrl: 'app/admin/views/panelAdmin.html',
title: {
'es': 'Panel de administración',
'en': 'Control panel',
'de': 'Führungspanel'
}
})
And in $stateChangeStart reload the title:
$rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
if (toState.title) {
$rootScope.title = toState.title[$rootScope.cultureLang];
}
});
In index.html:
<title>{{title}}</title>
I think we can use $rootScope for this purpose. Please see below.
html template
<body ng-app="myApp" >
{{viewTitle}}
<div ui-view=""></div>
</div>
</body>
js file
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/',
template: '<h1>From nested view </h1>',
controller: function($rootScope)
{
$rootScope.viewTitle = "home";
}
});
});
Hope it helps
I've a very strange problem, it apparently seems that simple views template are preventing a controller to be executed, I can't understand why.
I've built a simple plunker
Code is here:
angular.module('plunker', ["ui.router"])
.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise("/nested");
$stateProvider
.state('nested', {
url: '/nested',
controller: function($scope) {
$scope.sayHi = 'Hi';
this.sayHello = 'Hello';
},
controllerAs: 'dog',
//If I comment the "views" section, controller runs correctly
views: {
'main': {
template: 'MainContent'
},
'secondary': {
template: 'SecondaryContent'
}
}
})
$locationProvider.html5Mode(false).hashPrefix('!');
})
html:
<div ui-view>
<h1>{{dog.sayHello}}</h1>
<h1>{{sayHi}}</h1>
<p>Why no "hello" or "Hi" over here?</p>
<div ui-view="main"></div>
<div ui-view="secondary"></div>
</div>
If I comment out the "views" section in the state definition, controller runs correctly.
[edit]
Thanks to Radim, I resolved moving the controller definition in the views section:
views:{
'':{
controller: function ($scope) {
this.page = 'ten';
},
controllerAs:'dog'
},
'main#nested':{
template:'MainContent'
},
'secondary#nested':{
template:'SecondaryContent'
}
}
Check:
UI-Router Multiple Views Single Controller not work
The controller always belongs to view, not to state.
There is an updated plunker
.state('nested', {
url: '/nested',
//controller: function($scope) {
// $scope.sayHi = 'Hi';
// this.sayHello = 'Hello';
//},
//controllerAs: 'dog',
//If I comment the "views" section, controller runs correctly
views: {
'main': {
//template: 'MainContent', - let's use view, to consume dog.sayHello
templateUrl: 'view2.html',
controller: function($scope) {
$scope.sayHi = 'Hi';
this.sayHello = 'Hello';
},
controllerAs: 'dog',
},
'secondary': {
template: 'SecondaryContent',
controller: ...
}
}
check the updated plunekr
I'm learning angular, and have been trying to dynamically load a HTML file fragment into the content pane of a tab.
In this linked plunker I have created an angular module to configure the states
var app = angular.module('Plunker', ['ui.router', 'ui.bootstrap'])
app.config([
'$stateProvider',
'$urlRouterProvider',
function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state("tab1", { url: "/tab1", templateUrl: "tab1.html" })
.state("tab2", { url: "/tab2", templateUrl: "tab2.html" })
.state("tab3", { url: "/tab3", templateUrl: "tab3.html" });
$urlRouterProvider.otherwise('/');
}]);
app.controller("tabsController", function ($rootScope, $scope, $state) {
$scope.tabs = [
{ title: "My Tab 1", route: "tab1", active: true },
{ title: "My Tab 2", route: "tab2", active: false },
{ title: "My Tab 3", route: "tab3", active: false },
];
$scope.go = function (route) {
$state.go(route);
};
$scope.active = function (route) {
return $state.is(route);
};
$scope.$on("$stateChangeSuccess", function () {
$scope.tabs.forEach(function (tab) {
tab.active = $scope.active(tab.route);
});
});
});
and in the index.html body assign the ui-view a name to associate it with the state/route
<body ng-app="Plunker">
<div ng-controller="tabsController">
<uib-tabset>
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disable="tab.disabled">
<div ui-view="{{tab.route}}"></div>
</uib-tab>
</uib-tabset>
</div>
</body>
Each tab should have content coming from the respective html file fragment tab1.html, tab2.html or tab1.html. But I cant get it to work. Any help making this work would be much appreciated.
You want to have one partial for each tab. For that, the named views feature of ui-router can help you. You won't change state, but having the content on dedicated views allows you to keep the parent template light and nicely organize your code. Moreover you could reuse the tab templates elsewhere.
State definition where the tabset component resides:
$stateProvider
.state('example', {
url: '/example',
views: {
"tab1": { templateUrl: "tab1.html" },
"tab2": { templateUrl: "tab2.html" },
"tab3": { templateUrl: "tab3.html" },
}
Tabset definition:
<uib-tabset>
<uib-tab ng-repeat="tab in tabs" heading="{{tab.title}}" ...>
<div ui-view="{{tab.route}}"></div> <!-- ex: <div ui-view="tab1"></div> -->
</uib-tab>
</uib-tabset>
See updated plunker
I'm using AngularJS translate, and If I use it as says the tutorial from pascalprecht my angular app fail and it doesn't show anything (it doesn't load partial views), so I decided to use angular-translate-partial-loader
I have one app menu, and I have a MenuCtrl to display options, I want to translate this menu
Here Is my code
angular.module('myapp'['ngAnimate','ngAria','ngCookies','ngMessages','ngResource','ngRoute','ngSanitize', 'ngTouch', 'pascalprecht.translate'])
.value('language', 'bra')
.run(function ($rootScope, $translate)
{
$rootScope.$on('$translatePartialLoaderStructureChanged', function ()
{
$translate.refresh();
}
);
})
.config(function($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'translations/{lang}/{part}.json'
});
$translateProvider.preferredLanguage("bra");
})
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/about', {
templateUrl: 'views/about.html',
controller: 'AboutCtrl'
})
.otherwise({
redirectTo: '/'
});
});
angular.module('myapp')
.controller('MenuCtrl', function ($scope, $translatePartialLoader) {
$translatePartialLoader.addPart('menu');
$scope.lItems = [
{
title: "HOME",
class:'active',
href:'/',
visible: true
},
{
title: "CLASSROOMS",
class:'',
href:'#',
visible: true
},
{
title: "EXPENSES",
class:'',
href:'#',
visible: true
},
{
title: "EARNINGS",
class:'',
href:'#',
visible: true
},
{
title: "STUDENTS",
class:'',
href:'#',
visible: true
}
];
});
In index.html
<div id="navbar" class="navbar-collapse collapse" ng-controller="MenuCtrl">
<ul class="nav navbar-nav" ng-repeat="lItem in lItems">
<li class="{{lItem.class}}">{{lItem.title | translate}}</li>
</ul>
</div>
Can you help me?
Thanks!
Finally I found the solution.
The trouble was that the menu is out of ng-view block, and when the app loads doesn't refresh the correct html part.
By adding this $translatePartialLoaderProvider.addPart('menu');
.config(function ($translateProvider, $translatePartialLoaderProvider) {
$translatePartialLoaderProvider.addPart('menu');
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: 'translations/{lang}/{part}.json'
});
$translateProvider.preferredLanguage('bra');
....
When the application loads the menu part is also loaded.
Trying to show hide menus based on user login using a custom directive. It all works fine in the views templates but in header it does not work [header is a different template]. It works fine on page refresh though.
header.html
<div id="header" class="navbar">
<a class="navbar-brand" href="#">My APP</a>
<ul class="nav nav-pills">
<li has-logged="!in">Sign Up</li>
<li has-logged="in">Home</li>
</ul>
</div>
has-logged directive
angular.module('myApp')
.directive('hasLogged', function(CookieService) {
return {
link: function(scope, element, attrs) {
if(!_.isString(attrs.hasLogged))
throw "hasLogged value must be a string";
var value = attrs.hasLogged.trim();
var notLoggedFlag = value[0] === '!';
if(notLoggedFlag) {
value = value.slice(1).trim();
}
function toggleVisibilityBasedOnLogin() {
var logged = CookieService.getLoginStatus();
if(logged && !notLoggedFlag || !logged && notLoggedFlag)
element.show();
else
element.hide();
}
toggleVisibilityBasedOnLogin();
}
};
});
app.js config
var myApp = angular.module('myApp',['ngRoute','ngCookies']);
myApp.config(function ($routeProvider,$httpProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/module/public/index.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/login', {
templateUrl: 'app/module/login/login.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/home', {
templateUrl: 'app/module/home/home.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/register', {
templateUrl: 'app/module/register/register.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.otherwise({redirectTo: '/'});
});
Code to add header and footer on app run
// Adds Header and Footer on route change success
$rootScope.$on('$routeChangeSuccess', function (ev, current, prev) {
$rootScope.flexyLayout = function(partialName) { return current.$$route[partialName] };
});
I tried this POST solution but still the same effect.
How do i change the menus without page refresh??
You may look into ui-router. It supports multiple and nested views.
Demo Fiddle
Click on First and Second to navigate between both states.
Here is the basic setup
First you need the views:
<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>
Then some sort of navigation to switch between ui states:
<ul>
<li>First</li>
<li>Second</li>
</ul>
Here is a basic state configuration:
myApp.config(function($stateProvider, $urlRouterProvider) {
// default route
$urlRouterProvider.otherwise("/first");
// ui router states
$stateProvider
.state('first', {
url: "/first",
views: {
header: {
template: '<h1>First header</h1>',
controller: function($scope) {}
},
content: {
template: '<p>First content</>',
controller: function($scope) {}
},
footer: {
template: '<div>First footer</div>',
controller: function($scope) {}
}
}
})
.state('second', {
url: "/second",
views: {
header: {
template: '<h1>Second header</h1>',
controller: function($scope) {}
},
content: {
template: '<p>Second content</>',
controller: function($scope) {}
},
footer: {
template: '<div>Second footer</div>',
controller: function($scope) {}
}
}
});
});