Ionic UI Router not working for child view - ionic-framework

I'm trying to create a very simple lookbook application. Yet I can't seem to get the routes to work. I tried the answer to this question to debug the routes. Nothing appeared in the console.
I'm trying to create an application where the user sees several looks on a page and can then navigate to the respective details page. It would be nice if Ionic also recognizes that the details page is a child page of the lookbook page. Thus showing the back button in the menu bar.
The app.config route setup code:
$stateProvider
//Lookbook view
.state('lookbook', {
url: '/lookbook',
views: {
'main': {
templateUrl: 'templates/lookbook.html',
controller: function () {
console.log('Lookbook controller loaded!');
}
}
}
})
// Details view
.state('lookbook.brand-shirt', {
url: '/lookbook/brand-shirt',
views: {
'main': {
templateUrl: 'templates/brand/shirt.html',
controller: function () {
console.log('Details controller loaded!');
}
}
}
});
$urlRouterProvider.otherwise('/lookbook');
The index.html <body> contents:
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-title>
<img class="logo" alt="Lookbook Logo" ng-src="assets/images/icons/logo.svg">
</ion-nav-title>
</ion-nav-bar>
<ion-nav-view name="main">
</ion-nav-view>
The lookbook page shows up. But when I navigate to /lookbook/brand-shirt it reverts back to /lookbook.
What is it that I'm missing?

In that routing, the brand-shirt state is a child of the lookbook state (lookbook.brand-shirt), as you don`t want to load the detail INSIDE the lookbook view, you don't need to make it like that.
$stateProvider
//Lookbook view
.state('lookbook', {
url: '/lookbook',
views: {
'main': {
templateUrl: 'templates/lookbook.html',
controller: function() {
console.log('Lookbook controller loaded!');
}
}
}
})
// Details view
.state('brand-shirt', {
url: '/lookbook/brand-shirt',
views: {
'main': {
templateUrl: 'templates/brand/shirt.html',
controller: function() {
console.log('Details controller loaded!');
}
}
}
});
$urlRouterProvider.otherwise('/lookbook');
Do it like that. And the history will work the same because you are pushing views in your 'main' ion-nav-view. So at the start of your app /lookbook is loaded in main, when you go to brand-shirt, that new view goes above in the main views stack. If you go back, you will be removing the details view and going back to the lookbook.
CodePen

Related

ionic modal using upload file with { FileUploader } from 'ng2-file-upload';

i want to make a uploading in modal page,but it shows error:
"NG0303: Can't bind to 'uploader' since it isn't a known property of 'input'."
but actually i have imported all the components including app.module.ts( entryComponents:[ModalPage])
my modal html page:
<ion-col>
<input type="file"
id="input-btn"
accept="."
ng2FileSelect
[uploader]="uploader"
multiple
(change)="selectedFileOnChanged(file)"
/>
</ion-col>
my modal ts :
public async selectedFileOnChanged(file: HTMLInputElement) {
this.uploader.queue[0].upload();
...
}
on my main page i click to call modal page
with below function to call:
async presentModal(obj: string) {
const modal = await this.modalController.create({
component: ModalPage,
swipeToClose: true,
mode: "ios",
cssClass: 'my-custom-class',
presentingElement: this.routerOutlet.nativeEl,
componentProps: {
'firstName': obj,
'lastName': 'Adams',
'middleInitial': 'N'
}
});
await modal.present();
}
how to use all other components correctly in ionic modal
thank you very much

Reload data in a component Ionic

I'm using Ionic and Firestore for my web appllication. In a component I show a list of items from firestore database,the detail of an item in url tabs/items/list-detail/ and other button to modify images, then there is a button to return the url tabs/items/. Afterwards, if I return to the tabs/items/list-detail page I would like the list to be reloaded with the modified items, but the page remains the same.
I have tried using ViewWillEnter but doesn't work.
In html page of items there is a button to navigate to detail page:
<ion-button id="detail" *ngIf="registeredAndUpl?.registered!=true" [routerLink]="['/tabs/items/list-detail',id]">View</ion-button>
This is the component list-detail Page:
export class DetailPage implements OnInit, ViewWillEnter {
items: any
userId: any
item0: any
item1: any
constructor(private route: ActivatedRoute, private router: Router,
public authService: AuthenticationService,
) {}
ngOnInit() {
}
ionViewWillEnter() {
this.myDefaultMethodToFetchData();
}
myDefaultMethodToFetchData() {
console.log("IN")
this.getItems().then((data) => {
console.log("IN2222")
this.items = data
this.item0 = this.items[0];
this.item1 = this.items[1];
})
this.userId = this.authService.userData.uid;
}
returnItems(){
this.router.navigate(['/tabs/items/']);
}
getItems() {
const itemsRef = firebase.firestore().collection("user_orders/" + this.userId+"/reservations")
.where("ordini", "<", 10).limit(5);
return itemsRef.get()
.then((querySnapshot) => {
return querySnapshot.docs.map(doc => doc.data());
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
}
Then, in html page I have a button to return the items:
<ion-content>
<div class="flexbox-container" style="display:flex;">
<div *ngIf="item0" class="sidebar" style="flex:1;">
<video id="video1" height="320" width="240" controls>
<source src="{{item0?.downloadURL}}" type="video/mp4">
<source src="{{item0?.downloadURL}}" type="video/ogg">
</video>
</div>
<div *ngIf="item1" class="main" style="flex:1;">
<video id="video2" height="320" width="240" controls>
<source src="{{item1?.downloadURL}}" type="video/mp4">
<source src="{{item1?.downloadURL}}" type="video/ogg">
</video>
</div>
</div>
</ion-content>
<ion-button id="button1" (click)="returnItems()">Return</ion-button>
What am I doing wrong?
I've noticed that every time I switch from items to list detail page, using the ionViewWillEnter() method, and try to print something in console, the print is recalculated but the data remain the same, so the problem I think is in html page:
ionViewWillEnter should work. Try ionViewDidEnter.
Maybe is late for an answer in this question but i think will be useful for future users.
Related to OP question the mos efficient way is that using Events. It is something similar of use of custom events in javascript.
Using events you can do or refresh everything even in cached pages/components.
Below shows how you can subscribe a listener then call the event from everywhere, doing that listener to intercept the event you have raised.
Page that needs to be refreshed after back button is pressed
page.ts
constructor(
private events: Events
) {}
ngOnInit() {
this.events.subscribe('back_refresh', (data) => { /*Do your operations here as it's always called */ });
}
Page where back button is present
page.html
<ion-back-button (click)="this.goBack()"></ion-back-button>
page.ts
constructor(
private navController: NavController,
private events: Events
) {}
private goBack(): void{
this.navController.pop();
// also you can pass your data here
this.events.publish('back_refresh', null);
}

What is the need of $scope.closeModal?

Here is my code..If I remove close modal function,there is no effect. If I click any where outside the modal, the modal closes. But I need this close modal function as I need to set a flag in it for further use. How can I proceed further?
$scope.$on('$ionicView.afterEnter', function() {
$scope.openModal();
}
$ionicModal.fromTemplateUrl("settings/settingsModal.html", {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function(){
$scope.modal.show();
}
$scope.closeModal = function(){
$scope.modal.hide();
};
}
There are a two ways of implementing modal in Ionic. One way is to add separate template and the other is to add it on top of the regular HTML file, inside script tags. First thing we need to do is to connect our modal to our controller using angular dependency injection. Then we need to create modal. We will pass in scope and add animation to our modal.
After that we are creating functions for opening, closing, destroying modal and the last two functions are place where we can write code that will be triggered if modal is hidden or removed. If you don't want to trigger any functionality when modal is removed or hidden you can delete the last two functions.
Controller's Code:
.controller('MyController', function($scope, $ionicModal) {
$ionicModal.fromTemplateUrl('my-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
});
HTML Code :
<script id = "my-modal.html" type = "text/ng-template">
<ion-modal-view>
<ion-header-bar>
<h1 class = "title">Modal Title</h1>
</ion-header-bar>
<ion-content>
<button class = "button icon icon-left ion-ios-close-outline"
ng-click = "closeModal()">Close Modal</button>
</ion-content>
</ion-modal-view>
</script>
There are also other options for modal optimization. I already showed how to use scope and animation. The table below shows other options.
Modal options
The close modal function is meant for situations where you would like to close the modal manually. For example after a certain time it has been open or if something happens/the user does something for example presses a button.
There are ways of listening to when the modal is hidden/removed which will suit your situation and needs. For example:
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
console.log('modal was hidden');
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
console.log('modal was removed');
});
With these you should be able to do what I understood you are wanting to do.
Straight from the documentation: http://ionicframework.com/docs/api/service/$ionicModal/

Ionicmodal Doesn't Open Until Third Click/Tap

I have set the on-tap value of a div to open a modal which is defined in the page's controller. The div is part of an ng-repeat section. The modal function also accepts some variables passed to it by the div.
When the app is first started on my device (iPhone 6 running iOS 7), I have to tap the div three times before the modal will open. After that, it opens consistently when I tap. But when the app first starts, I have to tap the div 3 times.
There are no errors at all in the console. Once the modal does open, it works as expected.
Any advice?
Here's the code:
HTML
<div on-tap="doModal('{{embed.ID}}','reply','{{embed.oembed}}','{{embed.user}}');">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75 72" width="100" height="50">
<path d="imagestuffhere"/>
</svg>
</div>
CONTROLLER
$scope.doModal = function(this_ID,modaltype,this_oembed,this_user) {
$scope.contact = {
name: this_ID,
info: modaltype,
oembed: this_oembed,
user: this_user
}
if (modaltype == 'repost') {
$scope.modaltempl = 'templates/repost-modal.html';
}
else if (modaltype == 'reply') {
$scope.modaltempl = 'templates/reply-modal.html';
}
else if (modaltype == 'like') {
$scope.modaltempl = 'templates/like-modal.html';
}
else {
$scope.modaltempl = 'templates/like-modal.html';
}
$ionicModal.fromTemplateUrl($scope.modaltempl, {
scope: $scope,
animation: 'slide-in-up'
}).then(function (modal) {
$scope.modal = modal;
$scope.modal.show();
console.log($scope.modaltempl);
});
};
$scope.closeModal = function() {
$scope.modal.hide();
};
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
I've tried pulling the $ionicModal.fromTemplateUrl($scope.modaltempl, bit outside of $scope.doModal and calling $scope.modal.show from within $scope.doModal, but the result is the same.
It definitely gets to the scope.modal.show(); statement even when the modal does not open, because the console.log I've included just after it gets output.
Before I had added the svg to the interface, I was testing this using a button element and had the same issue. It also had the same issue when I used ng-click instead of on-tap.
Thanks for any help!
Turns out the issue was not in the Ionic controller code nor the triggering html, but in the modal template, itself.
Per the Ionic documentation, I had each of my modal templates wrapped in this:
<script type="text/ng-template" id="repost-modal.html"></script>
By removing that and replacing it with just <ion-modal-view></ion-modal-view> the issue was resolved and the modals now open very nicely on the first click.

Ionic Framework - Using Same View for Multiple Tabs

I know this has been addressed a few times, but I am trying to figure out the right way to architect this solution:
I have 5 tabs, where all 5 tabs, where in these tabs, I need to use the same view and the same URL for multiple tabs. For example:
feedTab (/feed, tab is tab-feed) -> checkinDetail (checkin/:checkinId) -> ItemDetail (item/:itemId)
profileTab (/profile, tab is tab-profile) -> checkinDetail (checkin/:checkinId) -> ItemDetail (item/:itemId)
Is this possible? If not - what is the best way to do this in ionic using Tabs?
I have done this, you just need to define a state for each of the possible detail views. For example:
In my application I have a detail view that can be accessed from more than one tab.
templates/ride-detail.html
I have two tabs that can access the above detail view:
tab.profile
tab.rides
and they have states defined as below:
.state('tab.profile', {
url: '/profile',
views: {
'tab-profile': {
templateUrl: 'templates/tab-profile.html',
controller: 'ProfileCtrl'
}
}
})
.state('tab.rides', {
url: '/rides',
params: {
issearch: null,
radius: null
},
views: {
'tab-rides': {
templateUrl: 'templates/tab-rides.html',
controller: 'RidesCtrl'
}
}
})
To enable the ride detail view to be accessed from the two above tabs I defined two states for this as below:
.state('tab.ride-detail', {
url: '/rides/:rideId',
views: {
'tab-rides': {
templateUrl: 'templates/ride-detail.html',
controller: 'RideDetailCtrl'
}
}
})
.state('tab.profile-detail', {
url: '/profile/:rideId',
views: {
'tab-profile': {
templateUrl: 'templates/ride-detail.html',
controller: 'RideDetailCtrl'
}
}
})
Then from the rides tab I call code below to get to detail view:
$state.go('tab.ride-detail', {
rideId: rideid
});
and from profile tab call:
$state.go('tab.profile-detail', {
rideId: rideid
});
Then in your view you can have ng-click="godetail(checkinId)"
and then change state call depending on the controller that the godetail function calls into, so in my case when godetail is called from profile tab:
$scope.godetail = function (rideid) {
$state.go('tab.profile-detail', {
rideId: rideid
});
};
and when called from rides tab:
$scope.godetail = function (rideid) {
$state.go('tab.ride-detail', {
rideId: rideid
});
};
Hope this helps.