This should be pretty straight forward, but it def is not.
In my html i have 4 tabs, one of which is the default and the other 3 are manually disabled the ion-tab...my tabs are the standard ion template (static) tabs:
<ion-tab class="tabs-icon-top tabs-color-active-positive">
<ion-tab id="tab1" disabled="pageFlow.disableOtherTabs" ...>
<ion-nav-view name="tab1"></ion-nav-view>
</ion-tab>
<ion-tab id="tab2" disabled="pageFlow.disableOtherTabs" title="Tab2" icon-off='ion-off' icon-on='ion-on' href="#/tab/tab2">
<ion-tab id="tab3" disabled="true" ...>
<ion-tab id="tab4" disabled="true" ...>
</ion-tab>
This is working correctly...Tabs icons 2/3/4 visible but are greyed out and cannot be clicked. I then only have .controllers for tab1, tab2, tab3, tab4, but no controller for any kind of master "tabs" page.
In tab1 is a form, when the form is submitted, it is evaluated in the .controller and based on certain conditions is supposed to "enable" the 3 disabled tabs.
I have tried many many combinations to get them to enable so they won't be greyed out and can now be clicked - but NOTHING is working.
various things I have tried:
document.getElementById('tab2').disabled = false ;
angular.element(document.getElementById('#tab2').disabled = false ;
$ionicTabDelegate.select(1).disabled = false ; // this actually executes the tab1 controller/services but does not enable the icon - still can't click on it.
...and lord knows how many other combinations. But nothing is working. I have even defined "delegate-handle" and "ng-attr-id" to try and gain access to the ion-tab attributes - but again, nothing is working.
My tabs are define
Try creating a model like this in your controller which you will bind to in your HTML to dynamically change the rendering:
$scope.pageFlow = {
disableOtherTabs : true
}
Then when you submit your form change the value:
$scope.pageFlow.disableOtherTabs = false;
Finally, bind the model to your tabs:
<ion-tab id="tab2" disabled="pageFlow.disableOtherTabs" title="Tab2" icon-off='ion-off' icon-on='ion-on' href="#/tab/tab2">
Use the same property on all the tabs if you want them all to be enabled or add extra properties to control individual tabs.
UPDATED
In your app.js add a controller to your base tab:
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html",
controller: "tabsController"
})
Obviously inject it into your main html page and then this controller should be called before your navigate to "tab.tab1" which has your form. In this controller define your model from above. You will still need one more step however.
On your new controller add something like:
var refreshFinalizer = $rootScope.$on('updateTabsRefresh', function (event, data) {
$scope.pageFlow.disableOtherTabs = false;
});
$scope.$on('$destroy', function () {
refreshFinalizer ();
});
On your tab1 after the form is checked add the broadcast to the listener:
$rootScope.$broadcast('updateTabsRefresh');
Related
I'm working on a Cordova/Ionic 2/AngularJS project and I'm facing the following issue. I have defined 5 main navigation tabs with the corresponding views, but I have one view (this one contains an iFrame), which I want to navigate to from any of my main tabs, the problem is I need to keep the active tab selected
My tabs definition look like this:
<ion-tabs ng-controller="BaseTabs as ctrl"
class="tabs-icon-top tabs-color-active-positive"
delegate-handle="tabs">
<ion-tab title="Featured" icon="featured" ng-click="ctrl.openCatalog()"
ui-sref="tab.app-catalog.featured" on-select="ctrl.update()">
<ion-nav-view name="tab-app-home"></ion-nav-view>
</ion-tab>
<ion-tab title="Catalog" icon="shop" ng-click="ctrl.openCatalogSearch()"
ui-sref="tab.app-catalog-search" on-select="ctrl.update()">
<ion-nav-view name="tab-app-catalog-search"></ion-nav-view>
</ion-tab>
...
<ion-tab title="More" icon="more" ng-click="ctrl.openMore()"
ui-sref="tab.app-more-content" on-select="ctrl.update()">
<ion-nav-view name="tab-app-user"></ion-nav-view>
</ion-tab>
</ion-tabs>
in my iframe controller I have the following:
$stateProvider.state(
'tab.app-base-frame', {
url : '/base/frame:url',
parent : 'tab',
views : {
'tab-app-home' : {
templateUrl : 'templates/app/base/frame.html',
controller : 'BaseFrame',
controllerAs : 'ctrl'
}
},
params : {
url : ''
title : false
}
}
)
Since in the controller I have the views set tab-app-home, each time I open the iframe view I get the home tab selected instead of the one active before invoking the iframe.
So here is my question, is there a way to dynamically set the view based on parameters? Or maybe a more practical solution rather than the way I have done so far?
Thanks in advance for the help.
This is the solution that worked for me:
import {Tabs} from “ionic-angular”;
#Page({
template: <ion-tabs #paymentTabs [tabbarLayout]="tabBarLayout"
[selectedIndex]="tabsIndex" preloadTabs="false"> <ion-tab tabIcon="list-box"
tabTitle="Tab1" [root]="tab2"></ion-tab> <ion-tab tabIcon="list-box"
tabTitle="Tab2" [root]="tab2"></ion-tab> </ion-tabs>,
})
export class PaymentTab {
#ViewChild(“paymentTabs”) paymentTabs: Tabs;
constructor() {}
ngAfterViewInit() {
setTimeout(() => {
console.log(“this.paymentTabs”);
this.paymentTabs.select(1);
}, 500);
}
}
My abstract state is a frame with tabs that loads in the lower section a template depending on the active tab. The layout is similar to this:
The problem is that when I navigate back it also navigates through the tabs, instead of going to the previous state. How can I prevent this behaviour?
This is the template of my parent state
<ion-tabs>
<ion-tab ui-sref="home.user.details">
</ion-tab>
<ion-tab ui-sref="home.user.followers">
</ion-tab>
</ion-tabs>
<ion-nav-view class="inner-view"></ion-nav-view>
And this is my ui-router configuration
.state('home.user', {
url: '/user/:id',
abstract: false,
cache: true,
template: '<user></user>',
resolve: {
id: function($stateParams) {
return $stateParams.id;
}
}
})
.state('home.user.details', {
url: '/details',
templateUrl: 'template/user.details.html'
})
.state('home.user.followers', {
url: '/followers',
templateUrl: 'template/user.followers.html'
})
If you want to do this when the hardware backbutton is used you could do it with Ionic's onHardwareBackButton feature by manually setting the state where it should navigate to like this:
$ionicPlatform.onHardwareBackButton(onBackButton);
function onBackButton(e) {
$state.go('home.user');
}
You can register the above on the tab states and then remove it with offHardwareBackButton when the wanted behaviour changes like this:
$ionicPlatform.offHardwareBackButton(onBackButton);
I didn't see a back button but if you do have/want one replace it with a self made on and make it go to the parent state with something like this:
HTML:
<button class="button" ng-click="goToHome()">
<i class="icon ion-android-arrow-back"></i>
</button>
Controller:
$scope.goToHome = function() {
$state.go('home.user');
};
This could be a misunderstanding of how Angular controllers work, but I am trying to understand why the badge values for my tabs are not being updated.
I have isolated the issue to a Codepen here: https://codepen.io/tyman7/pen/JKKEbO
Extract from HTML:
<ion-tab title="Home" icon="ion-home" href="#/tab/home" badge="badgeValue" ng-controller="HomeTabCtrl">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
Extract from JS:
.controller('HomeTabCtrl', function($scope)
{
$scope.badgeValue = 1;
$scope.updateTabValue = function()
{
$scope.badgeValue += 1;
}
}
I ended up finding a solution that involves creating another controller that the badge value looks at. I have modified the isolated Codepen slighty to demonstrate: https://codepen.io/tyman7/pen/pbbRpb
Extract from HTML:
<ion-tab title="Home" icon="ion-home" href="#/tab/home" badge="badgeValue" ng-controller="HomeCtrl">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
Extract from JS:
.controller('HomeTabCtrl', function($scope)
{
})
.controller('HomeCtrl', function($scope)
{
$scope.badgeValue = 1;
$scope.updateTabValue = function()
{
$scope.badgeValue += 1;
}
}
The thing is, I just don't understand why it needs to be done this way. What fundamental knowledge am I missing here?
You had multiple instances of the HomeTabCtrl. It created one when the 'tabs' state was entered and another when the 'tabs.home' state was entered. Your 'tab' badgeValue was in one instance and the 'tabs.home' value another. An Easy fix to the original is to change the name of the 'tabs.home' controller to 'HomeCtrl' instead and create an empty controller of that name. Then the updateTabValue will be called in the parent scope and update the badgeValue throughout.
Here is a codepen:
http://codepen.io/stich12/pen/Nrrprd
I'm trying to populate an ion-content container. I want to load HTML into the $scope depending on which tab the user clicks:
<ion-tabs tabs-type="tabs-icon-only">
<ion-tab ...>
<ion-tab title="Create" icon-on="ion-android-create">
<ion-content padding="true" class="has-header">
{{getCreate}}
</ion-content>
</ion-tab>
<ion-tab ...>
</ion-tabs>
This is the controller for this view:
(function () {
'use strict';
angular.module('ionicApp')
.controller('HomePageController', ['$scope', '$state', '$templateCache', HomePageController]);
function HomePageController($scope, $state, $templateCache) {
$scope.getCreate = function() {
// at the moment create.html is just simple static html.
return $templateCache.get('app/views/home/ads/create.html');
//return $templateCache.get('main.create'); // this also doesn't work
};
}
})
();
The two relevant states are defined as:
.state('main.home', {
url: '/home',
views: {
'main': {
templateUrl: 'app/views/home/home.html',
controller: 'HomePageController'
}
}
})
.state('main.create', {
url: '/create',
views: {
'main': {
templateUrl: 'app/views/home/ads/create.html',
controller: 'CreateAdController'
}
}
})
Am I going about this incorrectly? What do I need to do to load create.html into $scope.getCreate in my HomePageController?
your approach seems a bit too complicated to me.
first of all you would have to make sure that your template has been loaded to $templateCache. this only happens when the template is rendered for the first time somewhere in the app (for example by using the "templateUrl" property)
alternatively you could fetch the data from the file by an ajax call on your own and compile it with the given $interpolate, $compile functions from angular. but then again: this seems way too complicated for this case.
secondly you would have to use ng-bind-html instead, because the way you did it there would be sanitized html to be seen. so there would be stuff like
etc instead of a compiled html version of it.
probably you should simply use the ng-include directive instead and everything will be fine in a blink of an eye ;)
As raised by #Patrick Kelleter, your approach is overly complex including working manually with the $templateCache and compiling HTML.
Why not use the router the way it's designed?
First, rename the state's view so that you can reference it explicitly:
.state('main.create', {
url: '/create',
views: {
'create': {
templateUrl: 'app/views/home/ads/create.html',
controller: 'CreateAdController'
}
}
})
Then change state using ui-sref= on the tab, and insert the state's template using <ion-nav-view ...> with the specially named view.
<ion-tabs tabs-type="tabs-icon-only">
<ion-tab ...>
<ion-tab title="Create" icon-on="ion-android-create" ui-sref="main.create">
<ion-content padding="true" class="has-header">
<ion-nav-view name="create"></ion-nav-view>
</ion-content>
</ion-tab>
<ion-tab ...>
</ion-tabs>
The router will then insert the content of app/views/home/ads/create.html into the <ion-nav-view name="create"> element when the tab is clicked.
Here is a full walkthrough: Build an App with Navigation and Routing - Part 1
Simply use $http.get:
$http.get($scope.template.url).then (function(response) {
console.log(response);
$scope.contents = response.data;
});
The DEMO on PLNKR.
The browser's Same Origin Policy and Cross-Origin Resource Sharing (CORS) policy may restrict whether the template is successfully loaded.
I have created a basic app with tabs. I have two tabs in my app, NEW and DISPLAY.
When I'm in the NEW tab, I redirect to an item in the DISPLAY tab: #/tab/display/1
Then when I click DISPLAY tab, or if I click NEW tab and then DISPLAY tab again, that same item page is shown - and the DISPLAY tab is using the DisplayItemCtrl instead of DisplayCtrl. With other words, I cannot get back to the original DISPLAY page (#/tab/display).
Is there a way to clear the history or some other way to fix this?
If I first visit the DISPLAY tab page before I go to the NEW tab page to create an item, it works, as if the route is cached, but if I don't visit the DISPLAY page when I start the app and create a new item, it will not work.
These are my states:
.state('tab.new', {
url: '/new',
views: {
'tab-new': {
templateUrl: 'templates/tab-new.html',
controller: 'NewCtrl'
}
}
})
.state('tab.display', {
url: '/display',
views: {
'tab-display': {
templateUrl: 'templates/tab-display.html',
controller: 'DisplayCtrl'
}
}
})
.state('tab.display-item', {
url: '/display/:id',
views: {
'tab-display': {
templateUrl: 'templates/display-item.html',
controller: 'DisplayItemCtrl'
}
}
})
I created a simple tabs app on codepen just to show the problem. http://codepen.io/anon/pen/GInjq First go to Dash, and click "Redirect to a friend". After that it will be impossible to reach the Friends tab start page.
This is an old post, but I still found a workaround, if someone has this issue look at my question.
Consists in putting ng-click="onTabSelected()" in the tab, and in the controller assigned to the tabs:
$scope.onTabSelected = function () {
$state.go("tab.home");
}
That way, always the tab is touched it will lead to the state I want, not the first shown or whatever, I hope it's useful for someone, the behaviour that gave the problem really looks like a bug in ionic.
Did you try state redirection from your tab?
For ex:
<ion-tab title="Contact" icon="ion-ios7-world" ui-sref="tab.display">
<ion-nav-view name="contact-tab"></ion-nav-view>
</ion-tab>
see documentation
http://ionicframework.com/docs/api/directive/ionTab/
<ion-tab
title="Tab!"
icon="my-icon"
href="#/tab/tab-link"
on-select="onTabSelected()"
on-deselect="onTabDeselected()">
</ion-tab>
create a function, onTabSelected that is called when the tab is clicked so that the ui-router doesnt manage it