Call ons-back-button by a function - onsen-ui

I'm new in Onsen UI. How should I use the 'go-back'-method to go back to the main page? (Like the left back button.) I've tried to do this with pushPage-Method. It works, but the animation is different.
HTML of the Template with the back / save-Button
<ons-navigator var="profileNavigator">
<ons-list ng-repeat="item in profileData">
<ons-list-item modifier="chevron" class="profile-list-item-container" ng-click="openAboutMeDesc(item.aboutMe)">
<div class="profile-list-item-left">
<i class="fa fa-child fa-profile-list"></i>
</div>
<div class="profile-list-item-right">
<div class="profile-list-item-content">
<div class="profile-category">Über mich
</div>
<span class="profile-desc">{{item.aboutMe}}</span>
</div>
</div>
</ons-list-item>
<ons-template id="profile-aboutme-desc.html">
<ons-page>
<ons-toolbar>
<div class="left">
<ons-back-button>Back</ons-back-button>
</div>
<div class="right">
<ons-toolbar-button ng-click="saveAboutMeDesc(item.naboutMe)">Save</ons-toolbar-button></div>
<div class="center">About</div>
</ons-toolbar>
<ons-row>
<!--my content-->
</ons-row>
</ons-page>
</ons-template>
</ons-navigator>
JavaScript
$scope.openAboutMeDesc = function (aboutMe) {
profileNavigator.pushPage('profile-aboutme-desc.html', { animation : 'slide' } );
};
$scope.saveAboutMeDesc = function (naboutMe) {
};

The animation is different (forward instead of backward) because, using profileNavigator.pushPage method, you are adding a new page to the stack instead of going back to an old one. If you need to go to the main page, consider using profileNavigator.resetToPage method.
$scope.openAboutMeDesc = function (aboutMe) {
profileNavigator.resetToPage('profile-aboutme-desc.html', { animation : 'slide' } );
};
Remember that you can select the transaction animation between "slide", "simpleslide", "lift", "fade" and "none".
Take a look at the official documentation if there is something not clear:
https://onsen.io/reference/ons-navigator.html
Hope it helps!

Related

ng-include height displays as 0 in ionic

Update:
Using ng-include height is 0. I've provided a totally simplified example below. I need to know how to fix this and make it so the page says Hello.
<ion-view title="Page">
<ion-content padding="true" class="has-header">
<div ng-include="'templates/page30'"></div>
</ion-content>
</ion-view>
Where the templates/page30 file is
<p>Hello</p>
Original Post:
I need to figure out how to get my ng-include to be shown within an ng-switch. Currently the code does not work. Two things aren't happening as expected. The outer button is way small and the ng-included sub-forms are not showing as their height is 0. Please keep in mind I am using Ionic which means I do not have access to *.height().
NOTE: I'm only showing step 1 of the ng-switch otherwise this would be too bulky.
<ion-view title="Some Template" hide-nav-bar="true">
<ion-content padding="true" class="has-header">
<div ng-controller="someCtrl">
<ng-switch on="step">
<div ng-switch-when="1">
<div height-bind height-value="containerHeight">
<ng-include src="'templates/somepage.html'"></ng-include>
</div>
</div>
</ng-switch>
</div>
</ion-content>
</ion-view>
I have built a directive that looks like the following:
llApp.directive('heightBind', function() {
return {
scope: {
heightValue: '='
},
link: function($scope, $element) {
$scope.$watch(function() {
$scope.heightValue = $element.prop('offsetHeight');
});
}
}
});
The template called by ng-include is the following:
<ion-view title="Services" hide-nav-bar="true">
<ion-content padding="true" class="has-header">
<div class="page-header">
<h1>
<span>Lawncare</span>Services</h1>
</div>
<ul class="list">
<li class="item item-checkbox">
Mow Lawn
<label class="checkbox">
<input type="checkbox">
</label>
</li>
<li class="item item-checkbox">
Trim Plants
<label class="checkbox">
<input type="checkbox">
</label>
</li>
</ul>
</ion-content>
</ion-view>
One last thing. The controller someCtrl looks like the following: (actual controller reference is missing because I'm currently working within ionic creator)
function($scope, $stateParams) {
// Set the step initially to 1 every time this controllwer is instantiated.
// Usually on ng-switch button update the
// step value via the setStep function provided
$scope.step = 1;
$scope.setStep = function(step) {
$scope.step = step;
}
$scope.containerHeight = 0;
}
Some of the other things I've looked at to solve this. I have looked at:
http://stackoverflow.com/questions/25108780/height-of-container-with-ng-repeat-directive-is-zero
As well as this plunker:
Plunker
You are setting the height to 0 in the controller:
$scope.containerHeight = 0;

Repeating the nested objects of a single element with angular

Most of the answers I've found are for repeating the entire object, and that works for me without problem. What I need is to display the objects of an element in an array. Here is my controller:
var app = angular.module('QLoad', []);
app.controller('loadCtrl', function($scope) {
$scope.question=[
{Id:'1', qText:'What\'s your Gender?',aCollection:[
{text:'Male',
icon:'fa fa-male fa-5x'},
{text:'Female',
icon:"fa fa-female fa-5x"}
]
},
{Id:'2', qText:'What kind of Pain do you have?',aCollection:[
{text:'Burning',
icon:'fa fa-fire fa-5x'},
{text:'Stinging',
icon:"fa-bee.png"}
]
}];
});
As I mentioned, I could easily do two nested ng-repeats and display everything, but I only need to display the answers for each individual question. That's why I have the following two views I've tried, but it neither works:
<h1>{{question[0].qText}}</h1>
<div ng-repeat="q in question">
<div ng-repeat="answer in q.aCollection" class="content">
<div class=button>
<i class="{{q[0].answer.icon}}" aria-hidden="true"></i>
{{q[0].answer.text}}
</div>
</div></div>
Nor does this work:
<h1>{{question[0].qText}}</h1>
<div ng-repeat="answer in question[0].aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div></div>
And this is where I'm stuck. I can't display a single question object and its nested array. Thank you for your help.
You can use [limitTo][1] filter to achieve that.
<div ng-repeat="q in question | limitTo:1">
<div ng-repeat="answer in q.aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div></div>
You can define an index which will be incremented with the ng-click.
Template
<h1>{{question[questionTrackIndex].qText}}</h1>
<div ng-repeat="answer in question[questionTrackIndex].aCollection" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
</div>
<div class="btn btn-warning" ng-if="questionTrackIndex != 0" ng-click="previousQuestion()">Previous</div>
<div class="btn btn-warning" ng-if="question.length - 1 > questionTrackIndex" ng-click="nextQuestion()">Next</div>
Controller
$scope.questionTrackIndex = 0;
$scope.question=[
{Id:'1', qText:'What\'s your Gender?',aCollection:[
{text:'Male',
icon:'fa fa-male fa-5x'},
{text:'Female',
icon:"fa fa-female fa-5x"}
]
},
{Id:'2', qText:'What kind of Pain do you have?',aCollection:[
{text:'Burning',
icon:'fa fa-fire fa-5x'},
{text:'Stinging',
icon:"fa-bee.png"}
]
},
{Id:'3', qText:'Question no 3',aCollection:[
{text:'Answer1',
icon:'fa fa-fire fa-5x'},
{text:'Answer2',
icon:"fa-bee.png"}
]
}
];
$scope.nextQuestion = function() {
$scope.questionTrackIndex++;
}
$scope.previousQuestion = function() {
$scope.questionTrackIndex--;
}
The variable $scope.questionTrackIndex has been used to scroll through the questions. I have added two buttons next and previous to scroll through the questions. With clicking next button, $scope.questionTrackIndex has been incremented and with clicking previous button, $scope.questionTrackIndex has been decremented.
See this PLUNKER
One of solution maybe is
<div ng-repeat="q in question">
<div ng-click="a($index)">{{q.qText}}</div>
</div>
<h1>{{answ.text}}</h1>
<div ng-repeat="answer in answ.answerList" class="content">
<div class=button>
<i class="{{answer.icon}}" aria-hidden="true"></i>
{{answer.text}}
</div>
and your controller look like
$scope.answ = {};
$scope.answ.text = $scope.question[0].qText
$scope.answ.answerList = $scope.question[0].aCollection;
$scope.a = function(index){
$scope.answ.text = $scope.question[index].qText
$scope.answ.answerList = $scope.question[index].aCollection;
}
Example you can see on link

onsen popover : url not taking variable

Not sure this is an issue with onsen-ui or me being a newbie with angularjs...
I've got a menu with 2 different popover. I wanted to use the same controler since they are similar. The only difference is the button that call it and the page used for the popover menu. So I have something like this
app.controller('PopoverController', function($scope) {
$scope.popurl = function(url) {
$scope.param = url;
};
ons.createPopover($scope.param,{parentScope: $scope}).then(function(popover) {
$scope.popover = popover;
});
$scope.show = function(e) {
$scope.popover.show(e);
};
$scope.destroy = function(e) {
$scope.popover.destroy(e);
};
});
And it gets called this way
<div class="right" ng-controller="PopoverController">
<ons-toolbar-button id="android-share" ng-click="popover.show($event); popurl('popover_share.html')">
<ons-icon icon="ion-android-share" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button id="android-more" ng-click="popover.show($event); popurl('popover.html')">
<ons-icon icon="ion-android-more-vertical" fixed-width="false"></ons-icon>
</ons-toolbar-button>
</div>
This is not working. if I change ons.createPopover($scope.param,{parentScope: $scope}).then(function(popover) by
ons.createPopover('whatever.html',{parentScope: $scope}).then(function(popover) {
Then it works but obviously display whatever.html all the time
So I guess my first question is why is it working when I hardcode the URL and doesn't when I use a variable ?
The second question is : Is there a simpler way to pass my argument to my controler ?
Thank you for your help !
There are two mistakes in your code:
you are trying to show the popover before it has been created.
when you click the toolbar-button you are calling two functions in sequence, without considering that maybe the second function will finish its execution before the first one. This will give an inconsistent result (the popover will be displayed before the new URL will be initialized).
You can solve your issues by creating the popover inside $scope.popurl(), after the URL has been initialized. You can also show the popover after it has been created. Don't forget to destroy the popover after you close it, as any button click will create a new instance of the popover.
HERE you can find a working CodePen example and here is the code:
HTML
<div class="right" ng-controller="PopoverController">
<ons-toolbar-button id="android-share" ng-click="popurl('popover_share.html', $event)">
<ons-icon icon="ion-android-share" fixed-width="false"></ons-icon>
</ons-toolbar-button>
<ons-toolbar-button id="android-more" ng-click="popurl('popover.html', $event)">
<ons-icon icon="ion-android-more-vertical" fixed-width="false"></ons-icon>
</ons-toolbar-button>
</div>
<ons-template id="popover_share.html">
<ons-popover direction="up down" cancelable>
<div style="text-align: center; opacity: 0.5;">
<p>This is "popover_share" popover!</p>
</div>
</ons-popover>
</ons-template>
<ons-template id="popover.html">
<ons-popover direction="up down" cancelable>
<div style="text-align: center; opacity: 0.5;">
<p>This is "popover" popover!</p>
</div>
</ons-popover>
</ons-template>
JS
ons.bootstrap()
.controller('PopoverController', function($scope) {
$scope.popurl = function(url, e) {
$scope.param = url;
ons.createPopover($scope.param, {
parentScope: $scope
}).then(function(popover) {
$scope.popover = popover;
$scope.show(e);
});
};
$scope.show = function(e) {
$scope.popover.show(e);
};
$scope.destroy = function(e) {
$scope.popover.destroy(e);
};
});
Hope it helps!

Onsen's Navigator - pushPage function

I implemented a controller to store the title of an item and a page link associated with the item.
myApp.controller('takeAwayListCtrl', function($scope)
{
$scope.items = [{itemName: 'Pizze', page: 'pizze_takeaway.html'}, {itemName: 'Pasta', page: 'pasta_takeaway.html'}, {itemName: 'Dessert', page: 'dessert_takeaway.html'}];
});
While the x.itemName is intrepreted correctly, the following code fails to interpret the page attribute x.page correctly when I pass it to the pushPage function for the navigator.
<script type="text/ons-template" id="takeaway.html">
<ons-navigator title="Navigator" var="myNavigator">
<ons-page>
<ons-toolbar>
<div class="center">Take Away</div>
</ons-toolbar>
<ons-list ng-controller="takeAwayListCtrl">
<ons-list-item modifier="tappable" ng-repeat="x in items">
<ons-button ng-click="myNavigator.pushPage( {{x.page}}, { animation : 'slide' } )" modifier="large--quiet">
{{ x.itemName }}
</ons-button>
</ons-list-item>
</ons-list>
</ons-page>
</ons-navigator>
</script>
Do I need to escape something ?
I don't think you need to wrap the x.page with an {{ }}.
Just use it directly like this:
<ons-button ng-click="myNavigator.pushPage(x.page, { animation : 'slide' } )"

angular ui.bootstrap.carousel call next()/prev() from $scope

How do I access the next()/prev() methods of the carousel from the slide? I'm trying to connect to hm-swipe-left/right, but I don't seem to have the right $scope
<carousel interval="1000">
<slide ng-repeat="card in slides" active="card.active">
<div class="card list-unstyled text-center">
<ul class='header list-inline list-unstyled'
hm-swipe-left="swipe('next')"
hm-swipe-right="swipe('prev')">
<li><i class="icon {{card.icon}} fa-3x"></i></li>
<li class="title">{{card.title}}</li>
</ul>
</div>
</slide>
</carousel>
I was looking for a solution to this. I'll post what I finally did:
In the controller where you have the carousel (make sure your html carousel has id="myCarousel"):
$scope.showNext = function(){
var index = ($('#myCarousel .active').index()+1)%(slides.length);
var modIndex = (((index)%(slides.length))+(slides.length))%(slides.length);
$scope.slides[modIndex].active=true;
}
$scope.showPrev = function(){
var index = ($('#myCarousel .active').index()-1)%(slides.length);
var modIndex = (((index)%(slides.length))+(slides.length))%(slides.length);
$scope.slides[modIndex].active=true;
}
Then in your HTML page:
<img ng-src="{{slide.image}}" style="margin:auto;" ng-swipe-right="showPrev()" ng-swipe-left="showNext()">
Hope it helps to anyone!
It works for bootstrap 3.0.2 (my version)
EDIT:
Edited the modulus (since there is a bug in javascript when calculating modulus: Javascript modulo not behaving)
Now it works! :)
In my case I was just able to do this
<div ng-swipe-left="$parent.$parent.prev()" ng-swipe-right="$parent.$parent.next()" uib-slide ng-repeat="product in vm.productList track by $index" index="$index">
I am not sure if doing $parent.$parent is advised but it worked perfectly for me and I did not have put jquery/html code in my controller.
Keep in mind I was inside a ng-repeat, it could also be $parent.next() outside of the ng-repeat.
You can get the scope of directive from DOM element and re-use it
var element = angular.element('.carousel .left');
if (element.length > 0 && element.scope && element.scope().prev) {
element.scope().prev();
}
// or
if (element.length > 0 && element.scope && element.scope().next) {
element.scope().next();
}
Here is a slightly simpler solution:
Javascript Controller
$scope.carouselNext = function() {
$('#carousel-main').carousel('next');
}
$scope.carouselPrev = function() {
$('#carousel-main').carousel('prev');
}
HTML View
<div id="carousel-main" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-main" data-slide-to="0" class="active"></li>
<li data-target="#carousel-main" data-slide-to="1"></li>
<!-- add indicators for any slides added -->
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div id="slide1" class="item active" ng-swipe-right="carouselPrev()" ng-swipe-left="carouselNext()">
<!-- img or content here -->
</div>
<div id="slide2" class="item" ng-swipe-right="carouselPrev()" ng-swipe-left="carouselNext()">
<!-- img or content here -->
</div>
<!-- add more slides as needed -->
</div>
</div>

Resources