Ionic stateProvider - show/hide back button dynamically - angularjs

I'm working on an Ionic app and I fully working left menu with working states.
Here's the menu code:
<ion-side-menu side="left">
<ion-header-bar class="bar-royal">
<h1 class="title">Example</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close ng-repeat="test in data"
ng-switch="test.ID"
ng-href="{{test.ID == 0 ? '#/app/test' : '#/app/details/' + test.iID}}"
class="item item-icon-right">
<div ng-switch-when="0"><span>{{test.Name}}</span></div>
<div ng-switch-default><span>{{test.Name}}</span>
</div>
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
very basic setup.
and the code with the states (coffescript):
angular.module('hgApp', ['ionic'])
.config [
'$stateProvider'
'$urlRouterProvider'
($stateProvider, $urlRouterProvider) ->
$stateProvider.state('app',
url: '/app'
abstract: true
templateUrl: './sections/menu/menu.html'
controller: 'menuList'
).state('app.details',
url: '/details/:testID'
views:
'menuContent':
templateUrl: './sections/details/testDetails.html'
controller: 'testDetails'
Now, here my problem:
I can navigate to app/details/{testID} from the list on the left menu, or from links that I have on my home page.
I need to be able to add a back button to the top bar of app/details/{testID} only if I got to the page using the links on the home page, but not if i got there from the left menu list.
both the menu list and the links on the home page use as href "#/app/details/{{test.ID}}"
How can I do that? I really have no clue at all.
Thanks in advance for any help.

Hi i had a similar situation where i had to hide the button if the form was editable so i did the following
<ion-nav-back-button ng-show="!$root.hideBack"></ion-nav-back-button>
Controller.js
$scope.makeEditable = function () {
$scope.isEditable = true;
$rootScope.hideBack = true;
};
so if the fields were editable the back button would dissapear. I hope this is of any help.
Another example is:
Use $ionicHistory in your controller before calling $state.go('app.details'). I guess you have different controller for Home page where you use $stage.go to go to the details page? so the code should look something like
app.controller('HomeCtrl', ["$scope", "$ionicHistory", function($scope, $ionicHistory) {
$scope.goToDetails = function() {
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('app.details');
}
}]);
Html
<button ng-click="goToDetails()"></button>

Interesting question by the way
I think you can accomplish the behaviour you want using $broadcast
Basically you have a function that is called when you click on the link that will tell the testDetails controller 'hey, we came from a link, do your stuff'
The testDetails controller will be expecting this call and display the button accordingly
Raw code:
app.controller('AnyCtrl',
function AnyCtrl ($scope) {
// Call this code on link click
$scope.$broadcast('fromlink', 'Some data');
});
app.controller('testDetails',
function testDetails ($scope) {
$scope.$on('fromlink', function (event, data) {
// Add button. Profit
});
});
You can find a link to a small article covering all possibilities here
https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/

Related

Title on ionic view [ion-view]

I have my controller as "chatnow" and replacing the $scope.iid for title using $stateParams. But the chat messages are updated in a separate variable. I can update the messages at the interface using the following code but title not printed. When i remove the controller name title gets printed and not the messages. Help me out where i am going wrong.?
App.js :
.state('chatnow', {
url: '/chatnow/:jid',
templateUrl: 'templates/chatnow.html',
controller: 'ChatNow'
});
Controller.js
.controller('ChatUserClick', function($rootScope, $scope, $stateParams, $ionicPopup, $state, SendMessage, SharedProperties, ChatMessageService, Profile) {
$scope.iid = $stateParams.jid;
$scope.userJid = $stateParams.jid;
var sharedData = SharedProperties.sharedObject;
var MC = this;
MC.list = ChatMessageService.getList($scope.curchatjid);
})
Chat.html
<ion-view title="{{MC.iid}}" ng-controller="ChatNow as MC">
<ion-content class="chat">
<ion-list>
<li class="item chat-msg-wrap" ng-class="{'msg-send': todo.dt == 'send'}" ng-repeat="todo in MC.list track by $index">
<div class="chat-msg">{{todo.msg}}</div>
</li>
</ion-list>
</ion-content>
</ion-view>
It is because you are using ng-controller with route/ state configuration. Remove the ng-controller from your view. When you use the ng-view directive, don't use the ng-controller along with it. The controller will be specified from the state configuration, in your case:
.state('chatnow', {
url: '/chatnow/:jid',
templateUrl: 'templates/chatnow.html',
controller: 'ChatNow as MC'
});
The answer to this has been mentioned in this: https://stackoverflow.com/a/36881457/3878940

Angular Router - Url changes but view does not load

I have just started to adapt the sample angular/ionic tab navigation app and have run into a problem.
When I click on a link in one view (a list of all journeys), I should be taken to a screen with details about that particular journey. (Adapted from the 'chats' in the sample app.
It doesn't quite work however. The URL changes to the expected URL but the view/page doesn't change at all. When I try to refresh the page, I am taken back to my default state/page.
The controllers are:
.controller('JourneysController', function($scope, $log, JourneyHandler) {
'use strict';
$log.debug('Activating the journey controller');
$scope.journeys = JourneyHandler.getJourneys();
})
.controller('JourneyDetailController', function($scope, $stateParams, $log) {
'use strict';
$log.debug('Activating the journey detail controller');
$scope.journey = {
journeyId: 0,
journeyStart: new Date()
};
})
The app.js defines the states as:
.state('tab.journeys', {
url: '/journeys',
views: {
'tab-journeys': {
templateUrl: 'templates/tab-journeys.html',
controller: 'JourneysController'
}
}
})
.state('tab.journey-detail', {
url: '/journey',
views: {
'tab-journey-detail': {
templateUrl: 'templates/journey-detail.html',
controller: 'JourneyDetailController'
}
}
});
$urlRouterProvider.otherwise('/tab/dash');
and the relevant templates are:
tab-journeys.html
<ion-view view-title="My Journeys">
<ion-content>
<ion-list>
<ion-item class="item-remove-animate item-avatar item-icon-right" ng-repeat="journey in journeys" type="item-text-wrap" href="#/tab/journey">
<h2>{{journey.journeyId}}</h2>
<p>{{journey.routeId}}</p>
<i class="icon ion-chevron-right icon-accessory"></i>
<ion-option-button class="button-assertive">
Delete
</ion-option-button>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
and journey-detail.html
<ion-view view-title="Journey Detail">
<ion-content>
<p>This is where the journey details will go.</p>
</ion-content>
</ion-view>
There are no errors in the console so I really can't understand why it's not working.
When I encountered this same problem, I discovered that the error occurs because the controller didn't load.
Comment the controller in the state declaration and see if it works. You will need to check the controller.

ionic/angular $state.go gives blank screen on change

I'm trying to implement a facebook login for my ionic app based on this tutorial Coenraets fb tutorial, but I am coming across some problems.
I use tabs in my app, but when I try and redirect a user to the login page (tab) if they are not logged in, the login page shows as being blank (the navigation bar is still at the top though). If I refresh the page though, the login page then shows correctly. I know it is at least trying to redirect the page because I can't go to other tabs, just always this blank login tab.
Here is where I declare my tabs:
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
//setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
.state('tab.login', {
url: '/login',
views: {
'tab-login': {
templateUrl: 'templates/tab-login.html',
controller: 'AppCtrl'
}
}
})
//example of another state
.state('tab.map', {
url: '/map',
views: {
'tab-map': {
templateUrl: 'templates/tab-map.html',
controller: 'MapController'
}
}
})
Here is what my Login Tab HTML looks like:
<ion-view title="Login" name="tab-login" hide-back-button="true" style="background: #1b5a83" hide-nav-bar="true">
<ion-content has-header="true" padding="true" ng-controller="AppCtrl">
<div class="list list-inset" style="background: #1b5a83">
<div class="item item-image" style="border:none;margin-top:50px;">
<img src="img/sociogram.jpg"/>
</div>
<button class="button button-block button-light" ng-click="facebookLogin()">
<i class="icon ion-social-facebook"></i>
Login with Facebook
</button>
</div>
</ion-content>
And here is where my redirection takes place inside the .run function:
.run(function($rootScope, $state, $ionicPlatform, $window, OpenFB) {
OpenFB.init(fbappid, 'http://localhost:8100/oauthcallback.html', window.sessionStorage);
$ionicPlatform.ready(function() {
$rootScope.$on('$stateChangeStart', function(event, toState) {
if (toState.name !== "tab.login" && toState.name !== "tab.logout" && !$window.sessionStorage['fbtoken']) {
$state.go('tab.login');
event.preventDefault();
}
});
$rootScope.$on('OAuthException', function() {
$state.go('tab.login');
});
})
Any ideas where I am going wrong??? Thanks
Make sure that in your templates/tabs.html is a named <ion-nav-view>, because in your state 'tab.login' you tell UI router to look for a view placeholder with the name 'tab-login'. So you need to define this in your template:
<ion-nav-view name="tab-login">
Or you change your state definition to use an empty view name, so it references your unnamed <ion-nav-view> in the parents state 'tab':
.state('tab.login', {
url: '/login',
views: {
'': {
templateUrl: 'templates/tab-login.html',
controller: 'AppCtrl'
}
}
})
In your linked example there is only one named view vor all states, see https://github.com/ccoenraets/sociogram-angular-ionic/blob/master/www/templates/menu.html#L7
Have a look at multiple nested views in UI router here: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views

ionic slide box not working with ng-repeat

i need to use a ionic slide box to show some images in my application. I used ionic slide box it does not seem to work with a ng-repeat.
this is my html part
<ion-view title="Promotions" ng-controller="PromotionsCtrl">
<ion-content class="has-header" scroll="true" padding="true">
<ion-slide-box>
<ion-slide ng-repeat="obj in promotions">
<img ng-src= {{obj.img}}>
</ion-slide>
</ion-slide-box>
</ion-content>
</ion-view>
my controller
.controller('PromotionsCtrl', function($scope, $http, $window, $ionicSlideBoxDelegate,$interval) {
$http.get( 'http://******.com/B*****/service2.php?q=promotions', { cache: true})
.then(function(res){
$scope.promotions = res.data['top'];
$ionicSlideBoxDelegate.update();
});
})
You have to use update() if you are using ng-repeat with slideboxes.
See here:
http://ionicframework.com/docs/api/service/%24ionicSlideBoxDelegate/
The newer version .rc4 of ionic updates the slide box on its own. Try updating your Ionic Lib.
This is my sample,the slide works,but when the delegate-handler updated,the parameter of the "does-contunue" can't work,I'm Still looking for a solution...
html:
<ion-slide-box on-slide-changed="slideHasChanged($index)" does-continue="true" auto-play="true" delegate-handle="image-viewer" style="height:30%;">
<ion-slide ng-repeat="slide in slideList">
<div class="box" style="background-image: url('{{slide.url}}');background-size:100% 100%;></div>
</ion-slide-box>
controller:
angular.module("myApp.controllers", ["myApp.services"])
.controller("myController", function ($scope, $ionicSlideBoxDelegate, myService,$timeout) {
$timeout(function(){
var slideList = myService.getSlides();
$scope.slideList = slideList;
$ionicSlideBoxDelegate.$getByHandle('image-viewer').update();
},2000)
})
service:
angular.module("myApp.services", [])
.factory("myService", function () {
return{
getSlides: function () {
var slideList = new Array();
slideList.push("imgs/a.jpg");
slideList.push("imgs/b.jpg");
slideList.push("imgs/c.jpg");
return slideList;
}
}
})
As #Karan said, the update is call by itself. But there is still some problems. As mentioned in the issue, you can disable the slider if the data is not ready. Then everything will be fine.

Angular + Ionic: Multiple Nav Stacks

I just started learning Angular + Ionic this week. What I'm trying to do is get something like this: http://codepen.io/calendee/pen/IAjoL.
Except, I'd like to have a "Back" button in the Nav Bar of the Tabs page that takes me back to the Sign In page. i.e. I'm trying to get the Sign In Page, and the Tabs page to be part of a separate nav stack.
I've tried a couple of things, but in all cases I can only either a) Render the back button, b) Get the content to show up in each tab. Not both. Any help would be greatly appreciated!
Thanks,
Saswat
Note: I'm not sure why, but Stack Overflow apparently needs some code for a codepen link. So here it is.
I was part of the team here at Taqtile that developed Pontofrio's mobile site (a well known Brazilian retail brand) that has a very similar effect to what your are looking for and we accomplished that using angularjs.
We used just css for the stacks element location/animation (which would be your code pen code, basically) but the trick for the views persistency is just the use of ui-router to keep the old views state alive while you move then.
Oh, it also allowed the user to go back states using the back button or swiping (using hammerjs and angular-hammer - when we developed it, the last stable angularjs release was still 1.1.5, so we sadly didn't have all touch events out of the box...)
Its actually quite easy. You need to add another parent state which will be your sign-in form. And, have the tabs following another parent state of which will have the navigating back button. Download the ionic starter app for tabs and change the app.js, controller.js and tabs.html. Create a signin.html, to know the flow.
//app.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.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 && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
.state('signin',{
url: '/signin',
templateUrl: 'templates/signin.html',
controller: 'signInCtrl'
})
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
templateUrl: 'templates/tabs.html',
controller: 'TabCtrl'
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.chats', {
url: '/chats',
views: {
'tab-chats': {
templateUrl: 'templates/tab-chats.html',
controller: 'ChatsCtrl'
}
}
})
.state('tab.chat-detail', {
url: '/chats/:chatId',
views: {
'tab-chats': {
templateUrl: 'templates/chat-detail.html',
controller: 'ChatDetailCtrl'
}
}
})
.state('tab.account', {
url: '/account',
views: {
'tab-account': {
templateUrl: 'templates/tab-account.html',
controller: 'AccountCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/signin');
});
In signin.html
<ion-view title="'Sign-In'" left-buttons="leftButtons" right-buttons="rightButtons">
<ion-content has-header="true">
<div class="list">
<label class="item item-input">
<span class="input-label">Username</span>
<input type="text" ng-model="user.username">
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" ng-model="user.password">
</label>
</div>
<div class="padding">
<button class="button button-block button-positive" ng-click="signIn(user)">
Sign-In
</button>
<p class="text-center">
Forgot password
</p>
</div>
</ion-content>
</ion-view>
In tabs.html
<!--
Create tabs with an icon and label, using the tabs-positive style.
Each tab's child <ion-nav-view> directive will have its own
navigation history that also transitions its views in and out.
-->
<ion-view>
<ion-content>
<button class="button button-positive" ng-click="GoBack()">back</button>
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
<!-- Dashboard Tab -->
<ion-tab title="Status" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="#/tab/dash">
<ion-nav-view name="tab-dash"></ion-nav-view>
</ion-tab>
<!-- Chats Tab -->
<ion-tab title="Chats" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/chats">
<ion-nav-view name="tab-chats"></ion-nav-view>
</ion-tab>
<!-- Account Tab -->
<ion-tab title="Account" icon-off="ion-ios-gear-outline" icon-on="ion-ios-gear" href="#/tab/account">
<ion-nav-view name="tab-account"></ion-nav-view>
</ion-tab>
</ion-tabs>
</ion-content>
</ion-view>
In Controller.js
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope) {})
.controller('TabCtrl',function($scope,$state){
$scope.GoBack = function(){$state.go('signin')};
})
.controller('signInCtrl',function($scope,$state){
$scope.signIn = function(user){$state.go('tab');}
})
.controller('ChatsCtrl', function($scope, Chats) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//
//$scope.$on('$ionicView.enter', function(e) {
//});
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
.controller('AccountCtrl', function($scope) {
$scope.settings = {
enableFriends: true
};
});

Resources