Ionic - Problem using two way binding to change a style. As example I am using background-color - ionic-framework

I think I have a very basic problem but I can't resolve it. So what I am trying to do is to implement a button in Ionic that when pressed change the style of a style. To keep it simple for now I try and change the background color of a div. However, it does not work neither does it give an error. (I use console page of browser to view changes, look for errors etc)
The code in the card.page.html page is
<ion-button
(click)="setStyle('red')"
[style.--background]="'pink'"
>
Some Button
</ion-button>
The code in the card.page.ts is
setStyle(value: string): void {
console.log('read More Works');
this.aColor = '#yellow';
console.log('read More still Works');
}
and that is it. Clicking on 'Some Button' button does not do anything except the logging but I am pretty sure it is not two way binding that is the issue as I tried just using for example trying with just some text as being the 'variable' I want to change and that worked fine.
I do appreciate any help :(
Thanks

You can use pre defined CSS styles for that. Something like this:
card.page.scss
#somediv {
&.initial-style {
background: #000;
}
&.dinamic-style {
background: #fff;
}
}
card.page.html
<div id="somediv" [class]="apply_styles ? 'dinamic-style' : 'initial-style'">
styles applied: {{ apply_styles }}
</div>
<ion-button (click)="changeStyle()">Change Style</ion-button>
card.page.ts
apply_styles: boolean = false;
changeStyle() {
this.apply_styles = !this.apply_styles;
}
Of course this is very simple. But I hope it can put you in the right direction.

Related

Material UI IconButton onClick doesn't let to handle event

I installed "#material-ui/core": "^4.9.2" and "#material-ui/icons": "^4.9.1".
In my form i have several rows, each row has an add button and a remove button. I want the remove button to remove the row from it was clicked. It works fine with regular Button with a "-" character in it. But i want it fancy, so i replaced my Button from an IconButton, and imported the icons to use
import {AddCircleOutline,RemoveCircleOutlineOutlined} from "#material-ui/icons";
And my IconButton looks like this:
<IconButton
onClick={props.onRemoveClick}
className="align-self-center"
color="info"
size="sm"
disabled={props.index > 0 ? false : true}
<RemoveCircleOutlineOutlined/>
</IconButton>
When the IconButton is hit, the onClick method is called (i know because of logs in my console) but i can't handle the event because it is now undefined.
The funny thing is that if i click on the button area that doesn't correspond to the icon, it works. But obviously i need it to work in the whole area of the button.
It is not a binding issue because i already tested it.
Any ideas?
Props that are not cited in the documentation are inherited to their internal <EnhancedButton />, so you need to use a wrapper.
<IconButton
onClick={(e) => props.onRemoveClick(e)}
className="align-self-center"
color="info"
size="sm"
disabled={props.index > 0 ? false : true}
<RemoveCircleOutlineOutlined/>
</IconButton>
Well you gave an idea. Since i needed an index to identify the row's button, i sended the index through a paramater on the onClick method, like this:
onClick={e => props.onRemoveClick(props.index)}
In this way i didn't need to handle the event. I also had to bind my method on the constructor:
constructor(props) {
super(props);
this.handleRemoveClick = this.handleRemoveClick.bind(this);
}
Now i got the behaviour wanted
You can see the github ussue here. There is some problem with typescript definition files but we can work around it.
Solution
I tried to solve it like in the github issue but didn't work. So this works for me.
const onClick = (e: any) => {
// e is of type any so the compiler won't yell at you
}
<IconButton onClick={(e) => onClick(e)}>
I don't know the reason but using e.currentTarget helped me to get the button that I wanted and not the material icon inside it.
onClick={(e) => {
return console.log(e.currentTarget)
}}

How to get input from ion-searchbar?

It is super easy problem but I just can't seem to figure this out (And yes I have read the documentation).
I am trying to get the input user puts in the ion-searchbar (in Ionic v4) after they the press search and put in a const/let.
Mah HTML
<ion-searchbar showCancelButton="focus" class=""></ion-searchbar>
I don't know how I should write the TS for this.
Thanks in advance :{)
Use (search) event to call your function. This event is fired when the user will click on the search button provided by the ion-searchbar.
To get the value entered in the searchbar, use $event.target.value which gets the value field of the tag which in this case is <ion-searchbar>
<ion-searchbar
showCancelButton
searchIcon="search"
animated
cancel-button-icon
(ionCancel)="hideSearch()"
(search)="yourSearchFunction($event.target.value)"
placeholder="Search Some Values">
</ion-searchbar>
To listen to changes as user types in the search bar:
<ion-searchbar
...
(ionInput)="yourInputChangeFunction($event.detail.value)">
</ion-searchbar>
Note: On Ionic 6+, (ionInput) strangely emits value on $event.target.value although, their documentation mentions $event.detail
In your .html file:
<ion-searchbar
[(ngModel)]="autocomplete.input"
(ionInput)="updateSearchResults()"
placeholder="Search for a place">
</ion-searchbar>
In your .ts file:
export class LoginPage{
autocomplete: { input: string; };
updateSearchResults() {
console.log(this.autocomplete.input) //search input will display
}
}
Hope this works.
Html file.
<ion-toolbar>
<ion-searchbar
debounce="1000"
(ionChange)="ionChange($event)">
</ion-searchbar>
</ion-toolbar>
ts file
ionChange(event) {
console.log(event.detail.value)
}
Always Read Documentation of API, Plugins or anything which you are looking for.
You will get data by using ionChange() or ionInput().
Use following code in HTML file
<ion-searchbar
showCancelButton="focus"
ionInput="getData()"
class="">
</ion-searchbar>
and in TypeScript.
public getData(){
//ur logic here
}
Get a reference to the searchbar using the #ViewChild directive:
View:
<ion-searchbar #search></ion-searchbar>
Component:
#ViewChild('search', {static: false}) search: IonSearchbar;
Thereafter, get the value of the ion-searchbar as follows:
const input = await this.search.getInputElement();
const searchValue = input.value;

Searchbar - search on 'enter' key

I'm very new to Ionic framework.
Following the docs I created a searchbar like this:
<ion-searchbar
[(ngModel)]="searchQuery"
[showCancelButton]="true"
(ionInput)="search($event)">
</ion-searchbar>
ionInput When the Searchbar input has changed including cleared.
This works as expected.
However I want a different behaviour. I don't want to trigger search($event) every time the input changes, but I couldn't find an output event that is emitted when the user hits the 'enter' key or clicks a button for example.
Is there a solution for this behaviour?
You should be able to add Angular 2 keyup bindings to elements such as keyup and click
Template:
<ion-searchbar #q
[showCancelButton]="true"
(keyup.enter)="search(q.value)">
</ion-searchbar>
Component TS:
search(q: string) {
console.log(q);
}
With Ionic 5 using Angular you have to wrap the ion-searchbar inside a form tag like this:
<form (ngSubmit)="hideKeyboard()">
<ion-searchbar (ionChange)="search($event)"></ion-searchbar>
</form>
In your component using Capacitor:
import { Plugins } from '#capacitor/core';
const { Keyboard } = Plugins;
...
hideKeyboard() {
Keyboard.hide();
}
Of course you could use the ngSubmit event to also search and not only hide the keyboard.
I was able to capture 'Enter' key click or 'search' key click with (search) output event
<ion-searchbar
(search)="search($event)">
</ion-searchbar>
Just to add to #daniel-rubambura 's answer.
You can use ngModel in conjunction with (search) to get the value.
HTML
<ion-searchbar
showCancelButton="never"
[(ngModel)]="searchTerm"
(search)="testFunc()"
></ion-searchbar>
.ts
searchTerm: string;
testFunc(){
console.log(this.searchTerm);
}

slideChangeStart event does not fire when I swipe

In my Ionic 1.3.1 app I am using the ion-slides component to display sections of a questionnaire:
<ion-slides options="vm.options" slider="data.slider">
<ion-slide-page ng-repeat="s in ::vm.sections">
<div class="bar bar-header bar-positive">
<button class="button button-small button-icon icon ion-chevron-left"
ng-click="vm.previous()"
ng-show="::$index !== 0"></button>
<h1 class="title">{{::s.text}}</h1>
<button class="button button-small button-icon icon ion-chevron-right"
ng-click="vm.next()"
ng-show="::($index + 1) < vm.sections.length"></button>
</div>
<ion-content class="has-header">
<div ng-if="s.include" ng-show="s.show">
<!--My content-->
</div>
</ion-content>
</ion-slide-page>
</ion-slides>
In my controller I listen for the slideChangeStart:
$scope.$on("$ionicSlides.slideChangeStart", function (event, data) {
alert('slideChangeStart');
vm.activeIndex = slider.activeIndex;
vm.propertySurvey.CurrentSectionIndex = vm.activeIndex;
//include is used on an ng-if so elements are removed from the dom
//and the number of watchers is reduced
//also, the slider displays the contents of the
//previous slide unless they are explicitly hidden
vm.sections[slider.previousIndex].include = false;
vm.sections[slider.previousIndex].show = false;
initialiseQuestions(vm.activeIndex);
});
When I click on my previous and next buttons, which call slider.slidePrev() or slider.slideNext(), the slideChangeStart event fires - and I see the alert. But if I slide the page using a gesture - the header changes as I expect but the event does not fire. I've tried switching the swipe off in my options without success (not my preferred solution anyway):
vm.options = {
noSwiping: true,
effect: 'fade'
}
UPDATE
I tried using slideChangeEnd but that event isn't firing either.
So I moved all my code into a single gotoSlide(index) method that I call from my next, previous and pagerClick methods - so that I don't rely on the ion-slides event.
And I added Ionic on-swipe directives to my ion-slide-page component to see if they would work:
<ion-slide-page ng-repeat="s in ::vm.sections"
on-swipe-left="vm.next()"
on-swipe-right="vm.previous()">
That made the swipe work in the Ripple emulator (where it wasn't working at all before), but it still doesn't work on any of my android devices. Again, the swipe events don't seem to fire.
I am using the Crosswalk plugin
The problem goes away if I remove the effect option. So this works:
vm.options = {
noSwiping: false,
speed: 300
}
And, since these are the default values anyway, I ended up removing the options object altogether.
NB replacing 'fade' with 'slide' did not work
Reference:
http://ionicframework.com/docs/api/directive/ionSlides/
I had a similar problem, and the above answer did not work for me, so I thought I'd share what did:
Per the Swiper API (which underlies ion-slides), you can add event based call backs directly to the widget.
The following worked for me (assuming the scope.slider object...)
//the 'slideChangeStart' event has a slider argument in its callback
scope.slider.on('slideChangeStart', function(slider) {
//do stuff - maybe you want to store the activeIndex
scope.indexIReallyCareAbout = slider.activeIndex;
});
The Swiper API gives a list of events that can named in the 'on' callback function under the header Callbacks

How to use Modal Pop up with Material Design Lite?

I recently started using the latest Desktop version of Google Material Design Lite, I figured it doesn't have a modal pop up and the team has not yet implemented it for the next release.
I have tried to include bootstrap model into it, but thats not working infect seems pretty messed, I believe with the classes/styles clashing with each others.
Any Idea what will work good as an replacement ??
Thanks for your help.
I was also looking for a similar plugin and then I found mdl-jquery-modal-dialog
https://github.com/oRRs/mdl-jquery-modal-dialog
I used this because the other one I found was having issue on IE11. This one works fine.
<button id="show-info" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
Show Info
</button>
Here a JSFiddle: https://jsfiddle.net/w5cpw7yf/
I came up with a pure JavaScript Solution for this
You can use the default bootstrap data attributes for the buttons, and make sure that your buttons and modals have their own unique IDs.
You need to have Material Design Lite's JS included before using this JavaScript
Check out the code. Any reviews are welcomed. :)
// Selecting all Buttons with data-toggle="modal", i.e. the modal triggers on the page
var modalTriggers = document.querySelectorAll('[data-toggle="modal"]');
// Getting the target modal of every button and applying listeners
for (var i = modalTriggers.length - 1; i >= 0; i--) {
var t = modalTriggers[i].getAttribute('data-target');
var id = '#' + modalTriggers[i].getAttribute('id');
modalProcess(t, id);
}
/**
* It applies the listeners to modal and modal triggers
* #param {string} selector [The Dialog ID]
* #param {string} button [The Dialog triggering Button ID]
*/
function modalProcess(selector, button) {
var dialog = document.querySelector(selector);
var showDialogButton = document.querySelector(button);
if (dialog) {
if (!dialog.showModal) {
dialogPolyfill.registerDialog(dialog);
}
showDialogButton.addEventListener('click', function() {
dialog.showModal();
});
dialog.querySelector('.close').addEventListener('click', function() {
dialog.close();
});
}
}
<!-- Button to trigger Modal-->
<button class="mdl-button mdl-js-button" id="show-dialog" data-toggle="modal" data-target="#upload-pic">
Show Modal
</button>
<!-- Modal -->
<dialog id="upload-pic" class="mdl-dialog mdl-typography--text-center">
<span class="close">×</span>
<h4 class="mdl-dialog__title">Hello World</h4>
<div class="mdl-dialog__content">
<p>This is some content</p>
</div>
</dialog>
I use MDL with bootstrap and the modal is displayed correctly after adding the data-backdrop attribute this to the modal element:
<dialog data-backdrop="false">
Hope it helps!