Ionic: reloading current child state from side menu causes loss of header - ionic-framework

I'm creating a simple Ionic menu app and I would like to reload the current state from the side menu.Here's a Plunkr to illustrate the problem.
In the 'Search' state, the current time is displayed. The desired behavior is the following: when I click 'Search' from the side menu, the time is refreshed, i.e. the controller is reloaded. This should happen even when I'm already on the Search page. In reality, the controller is of course much more complex, but this example is enough to illustrate the problem.
I started from the ionic 'menu' starter template. To be able to reload the state, I changed two things:
disabled view caching in app.js config function: $ionicConfigProvider.views.maxCache(0);
In menu.html, I'm passing ui-sref-opts to explicitly reload the state:
ui-sref="app.search" ui-sref-opts="{reload: true}"
The result is that the time is indeed updated, however, the header of the view is gone.
Any suggestions as to what I'm doing wrong?

try something like this in the routing:
.state('tab.home', {
url: '/home',
cache: false, //<-- FORCE TO CLEAR CACHE
views: {
'tab-home': {
templateUrl: 'templates/home/home.html',
controller: 'HomeController'
}
}
})

You can broadcast an event to achieve that. But if you want to keep it like that, you could use a parameter and it would be all right because basically the one in control of the date var is your menu and not your state.
So you could do this:
app.js
.state('app.search', {
url: "/search",
params:{
date: new Date()
},
views: {
'menuContent' :{
templateUrl: "search.html",
controller: 'SearchCtrl'
}
}
})
Menu item
<ion-item nav-clear menu-close ui-sref="app.search({date: updateDate()})">
Search
</ion-item>
controllers.js (App controller or specific menu controller)
.controller('AppCtrl', function($scope) {
$scope.updateDate = updateDate;
function updateDate(){
return new Date();
}
})
controllers.js
.controller('SearchCtrl', function($scope, $stateParams) {
$scope.now = $stateParams.date;
})

Related

ion-view cache & states with URL Parameters

The cache mechanism of the ion-views seems broken when using URL Parameters in the view.
$stateProvider.
.state('a', {
url: '/a',
templateUrl: 'templates/a.html',
controller: 'ACtrl'
})
.state('b', {
url: '/b/:id',
templateUrl: 'templates/b.html',
controller: 'BCtrl'
})
In this example the state 'a' is cached and works as expected. But the state 'b' is just cached if the same id appears twice. So /b/1 and /b/2 results in different ion-view dom elements.
I would expect that the same ion-view dom element is used for all calls to /b/:id.
Is this a bug or works as expected? In my situation I want the "other" behaviour, any idea how to archive this?
You can try this to delete the ui-routing cache.
.run(function($ionicPlatform,$rootScope,$templateCache) {
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
})
Worked for me.

How do I get the title of the current Router Config Aurelia

I want message to persist through all pages of my application, and be set after the view-model and view are bounded. Every page I have a very simple template.
<template>
<h1>${message}</h1>
</template>
The code behind is empty for each page ('Page1', 'Home', 'Page2').
Here is my app.js
import {inject} from 'aurelia-framework';
export class App {
configureRouter(config, router) {
config.title = 'Pathways';
config.map([
{ route: ['','home'], name: 'home', moduleId: 'home', nav: true, title:'Home' },
{ route: 'page1', name: 'page1', moduleId: 'page1', nav: true, title:'Page1' }
]);
// Create a binding to the router object
this.router = router;
}
attached() {
this.message = this.router.currentInstruction.config.title;
}
}
The problem is, when I first load the app. ${message} is blank. Then, when I navigate to page1, the message becomes Home !! I thought that maybe the currentInstruction was lagging behind, so I added another page. Page2 if you will, but it turns out no matter what I do after the first navigation the message is always Home
So on app initialization message is blank, and then upon the first navigation message will remain Home for the entirety.
My question is, what is the "Aurelia" way to get the title of each page the user is currently on? I would think injecting the router on each page is costly
I can see two options:
The first and easiest one is using a getter property that listens to router.currentInstruction. For instance:
#computedFrom('router.currentInstruction')
get message() {
if (this.router.currentInstruction !== null)
return this.router.currentInstruction.config.title;
}
Running Example https://gist.run/?id=b01abe2859bc2bea1af0f8d21fc2045f
The second option is using the EventAggregator. For example:
attached() {
this.subscription = this.ea.subscribe('router:navigation:success', () => {
this.message = this.router.currentInstruction.config.title;
});
}
detached() {
this.subscription.dispose(); //remember to always dispose the subscription
}
Running example https://gist.run/?id=7d30d4e8d479cc209ca9013e10e91505
They say we should try to avoid the EventAggregator. So, I'd go with the first option.
You can use router.currentInstruction.config.title direct on your app.html page and it will be updated every time then router title is changed (it's using one-way binding):
<h1>title: ${router.currentInstruction.config.title}</h1>
Best way (thanks comments):
${router.currentInstruction.config.navModel.title}

collection-repeat with angular component, what is happening?

I'm trying to use collection-repeat to display an angular component for each object in an array. I pass each object as parameter to an angular component but when I try to access the object in my component's controller I get undefined.
<ion-content>
<ion-list>
<ion-item
collection-repeat="user in users"
item-width="100%"
item-height="90px">
{{user}} //renders my user data correctly instantly
<usser user="user"></user>
</ion-item>
</ion-list>
</ion-content>
My component
angular
.module('app')
.component('user', {
templateUrl: 'components/user.html',
scope: true,
bindings: {
user: '<'
},
controller: function() {
console.log(self.user) //prints undefined
}
})
I've tried wrapping the console.log in a $timeout without success
Printing self displays {user: undefined} in my chrome console, but if I expand the object I can see that user contains the correct data (only for the some of the items)
Accessing self.user doesn't work
EDIT: I can't really understand what's going on..
controller: function() {
console.log(self.user) //prints undefined
setTimeout(function() {
console.log(self.user) // prints my data
}, 2000)
}
What am I doing wrong?
Thanks in advance!
Lost 3 hours to figure out this
This is a known issue at the moment with collection repeat. A fix
would require a refactor of collection repeat, which would be too big
of a change the moment.
Always check the issues on Github, [V] lesson learned

No ionic back button visable following view change via $state.go ionic

I have 2 views as follows
.state('tab.matches', {
url: '/matches',
views: {
'tab-matches': {
templateUrl: 'templates/bant-tab-matches.html',
controller: 'MatchesCtrl'
}
}
})
.state('tab.matches-detail', {
url: '/matches/:matchId/:userId/:userName',
views: {
'tab-matches': {
templateUrl: 'templates/bant-tab-matches-detail.html',
controller: 'MatchesDetailCtrl'
}
}
})
I have a button on a different view which on click calls a function in the controller as follows:
$scope.messageUser = function (postInfo) {
$state.go('tab.matches-detail', { matchId: var1, userId: var2, userName: var3 });
}
This redirects to the tab.matches-detail view as expected but a back button is not present. I would like the back button to redirect back to the parent view being tab.matches, or the view I originally redirected from. If I navigate from tab.matches to tab.matches-detail (when I have not redirected by $state.go) the back button is present. I however am going direct to tab.matches-detail when $state.go is called. As such I can no longer access tab.matches as if I click on another tab and then return to tab.matches it displays tab.matches-detail with no way to access the parent state of tab.matches. I can't figure out how to get the back button to display. I need this to be controlled from the controller rather than a href in the view as I need to call similar functionality from an Actionsheet where the logic is all controller side.
Apologies for the rather verbose explanation but I want to be clear on the issue.
Thanks in advance for your help.
Anthony
To resolve this issue I set the back button in the view as not visible by setting hide-back-button="true" in the <ion-view> tag, then added a button for the header as follows:
<ion-nav-buttons side="left" class="button-clear customButton">
<div class = "buttonMatchesInner" ng-click="matchesGoBack()">
<i class="ion-chevron-left matchLeftIcon"></i>
</div>
</ion-nav-buttons>
With the click event calling:
$scope.matchesGoBack = function() {
$state.go('tab.matches');
}

Multiple views with tabs causing jumping between views - Ionic

So I have a Bottom Tabbed interface, with a listed Contact View. When you click on a contact it takes you too a Contact Details View for that contact.
Both Views have additional ion-tabs within them. The first Contact View works as expected, you can tab between "Friends", "Favorites", and "Requests". The problem happens when you enter the Contact Details View, clicking on any tab for that Contact will successfully switch tabs, but immediately take you back to the Contact View screen.
Here's a Plunker that shows what I mean:
http://plnkr.co/edit/Iuu1xgilMbGhmOeVkYKg?p=preview
For some reason in this Plunker it's defaulting to the Requests tab. So click Favorites, then Friends.
Click on a Contact and then a Tab for that Contact. It will take you back to the first screen.
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.friends', {
url: '/friends',
views: {
'tab-friends': {
templateUrl: 'tab-friends.html',
controller: 'FriendsCtrl'
}
}
})
.state('tab.friend-detail', {
url: '/friend/:friendId',
views: {
'tab-friends': {
templateUrl: 'friend-detail.html',
controller: 'FriendDetailCtrl'
}
}
})
The way I got around this was to have three buttons that replicated the tabs but changed view within the primary tab.