readonly property on input does not prevent the keyboard to show - ionic2

I am trying to use a native date picker in Ionic 2 by handling the click event on the input:
<ion-item>
<ion-label stacked>Start</ion-label>
<ion-input type="datetime" readonly="true" placeholder="Choose a date" formControlName="date" (click)="onDateClick($event)" tappable></ion-input>
</ion-item>
But the readonly property does not seem to prevent the keyboard to show one first time, I have to click again in order to get the native date picker to show (handled in onDateClick($event)).
I tried to use the disabled property, which works but the style is different and somehow it looks like it is not a good pattern when using Reactive Forms...
Any idea how to prevent this first show of the keyboard?
***** EDIT *****
Here is the onDateClick function
onDateClick(e: Event) {
console.log('NewEventPage#onDateClick');
if (this.platform.is('cordova')) {
this.datePicker.show({
date: new Date(),
mode: 'datetime',
allowOldDates: false
}).then(
date => {
console.log('Picked date ', date);
this.startDate = moment(date);
this.newEventForm.get('date').setValue(moment(date).format('LLLL'));
},
err => console.log('Error occurred while getting date: ', err)
);
} else {
let tmp = new Date();
this.startDate = moment(tmp);
this.newEventForm.get('date').setValue(moment(tmp).format('LLLL'));
}
}

do it like this:
<ion-item>
<ion-label stacked>Start</ion-label>
<ion-input type="datetime" [readonly]="true" placeholder="Choose a date" formControlName="date" (click)="onDateClick($event)" tappable></ion-input>
</ion-item>
readonly is the input property of ion-input that's why it has to be written inside the brackets. You can find more info here.

Related

How to clear the typeahead input after a result is selected?

I'm using the ng-bootstrap typeahead component to search a customer database. When the user selects a customer from the typeahead results list, I navigate to a customer details page. I've got this working, but I want to clear the input field after navigation has taken place. I've tried setting the model to null or an empty string in the selectItem event logic, but this isn't working:
customer-search-typeahead.component.html
<template #resultTemplate let-r="result" let-t="term">
<div>
<div>
{{r.resource.name[0].given}} {{r.resource.name[0].family}}
</div>
<div>
{{r.resource.birthDate | date: 'dd/MM/yyyy'}}
</div>
</div>
</template>
<input type="text" class="form-control" [resultTemplate]="resultTemplate" (selectItem)="onSelect($event)"
[(ngModel)]="model" placeholder="Start typing a customer name..." [ngbTypeahead]="search"/>
customer-search-typeahead.component.ts
#Component({
selector: 'customer-search-typeahead',
template: require('./customer-search-typeahead.component.html'),
styles: [`.form-control { width: 300px; }`]
})
export class CustomerSearchTypeaheadComponent {
model: any;
searching: boolean;
constructor(private customerService: CustomerService, private router: Router) {}
onSelect($event) {
this.router.navigate(['/customers', $event.item.resource.id]);
this.model = null;
};
search = (text$: Observable<string>) =>
//omitted for brevity
}
The typeahead input looks like this after a selection has been made:
Solution
customer-search-typeahead.component.html
<input type="text" class="form-control" #input [ngbTypeahead]="search" (selectItem)="onSelect($event); input.value='' ">
customer-search-typeahead.component.ts
onSelect($event, input) {
$event.preventDefault();
this.router.navigate(['/customers', $event.item.resource.id]);
};
The issue you witnessing arises from the fact that the NgModel directive is updating model binding asynchronously and the actual model is updated after the onSelect method gets executed. So your model update gets overridden by the NgModel functionality.
Fortunately we (ng-bootstrap authors) got all the flex points in place to cover your use-case :-) There are a couple of things that you could do.
Firstly the $event object passed to the onSelect method has the preventDefault() method and you can call it to veto item selection (and as a result writing back to the model and input field update).
$event.preventDefault() will make sure that the model is not updated and the input field is not updated with the selected item. But text entered by a user will still be part of the input so if you want to clear up this as well you can directly update the input's value property.
Here is code demonstrating all those techniques together:
onSelect($event, input) {
$event.preventDefault();
this.selected.push($event.item);
input.value = '';
}
where input argument is a reference to the input DOM element:
<input type="text" class="form-control" #input
[ngbTypeahead]="search" (selectItem)="onSelect($event, input)">
Finally here is a plunker showing all this in practice: http://plnkr.co/edit/kD5AmZyYEhJO0QQISgbM?p=preview
The above one is template ref value solution.
This is for ngModel solution.
Html code:
<input type="text" class="form-control" [resultTemplate]="resultTemplate" (selectItem)="onSelect($event)"
[(ngModel)]="model" placeholder="Start typing a customer name..." [ngbTypeahead]="search"/>
Component code:
onSelect($event) {
$event.preventDefault();
this.model = null;
this.router.navigate(['/customers', $event.item.resource.id]);
};
$event.preventDefault();
for ngModel value change empty

ionic - how to go to a list and select and return back to the original with the selected value

I am trying to accomplish this using ionic/cordova:
on button press
goes to a new screen with a list
selects an item in the list
and returns to the original with the selected value.
Can someone give directions how to accomplish this and give an example how this is accomplished ? Thanks.
Please provide what you have already tried. However, I understand what you want:
Make sure all your pages/templates are set up inside app.js correctly, have a controller.js, and services.js.
Passing data between controllers is done through services, You can inject the service into each page's controller and using set() and get() methods to change and receive the value(s) accordingly.
HTML (First page):
<ion-view view-title="firstPage">
<ion-content>
<!-- Binds selected value to div -->
<div ng-bind="selected.selec"> </div>
<!-- Goes to next page -->
<button class="button" ng-click="next()">
Next
</button>
</ion-content>
</ion-view>
Controller (First):
.controller('firstPageCtrl', function($scope, $state, savedList) {
// Go to next page
$scope.next = function() { $state.go("secPage"); }
// Get selected value from service, savedList
$scope.selected = { selec: "" };
$scope.selected.selec = savedList.get();
})
HTML (Second Page):
<ion-view view-title="secPage">
<ion-content>
<!-- Radio buttons will only allow one value to be selected at one time -->
<ion-list>
<!-- Pass in value of radio button to update function -->
<ion-radio ng-model="choice" ng-value="'A'" ng-change="update('A')">Choose A</ion-radio>
<ion-radio ng-model="choice" ng-value="'B'" ng-change="update('B')">Choose B</ion-radio>
</ion-list>
<!-- Goes back to first page -->
<button class="button" ng-click="back()">
Go Back
</button>
</ion-content>
</ion-view>
Controller (Second):
.controller('secPageCtrl', function($scope, $state, savedList) {
$scope.back = function() { $state.go("firstPage"); }
// Send selected value to service, savedList
$scope.update = function(selec) {
savedList.set(selec);
}
})
Service:
.factory('savedList', function() {
var selec = "";
// Sets selec to what ever is passed in
function set(data) {
selec = data;
}
// Returns selec
function get() {
return selec;
}
return {
set: set,
get: get
}
})
https://docs.angularjs.org/guide/services

Add action to enter in ember textarea input helper

I have used addon ember-autoresize for my textarea to resize my textarea.
{{textarea type="text" placeholder="Comment" value=comment_text autofocus="autofocus" rows=1 max-rows=4 autoresize=true
enter="commentSave"}}
I want to trigger the action when user press enter.But it moves to next line when I press enter.How do I call the action when enter key is pressed in textarea.
Create component called custom-textarea.
in components/custom-textarea.js:
export default Ember.TextArea.extend({
didRender() {
this.$().keypress(function(event) {
if (event.keyCode == 13) {
event.preventDefault();
}
});
}
});
In template, use custom-textarea instead of textarea:
{{custom-textarea type="text" placeholder="Comment" value=comment_text autofocus="autofocus" rows=1 max-rows=4 autoresize=true
enter="commentSave"}}
See WORKING DEMO.
Approach to prevent default behavior taken from this answer.

Exclude input events in famous-angular from general Event

I'm writing a mobile app with famous/angular. A swipe to the right in any view reveals the menu. For this I have set up the following event handling:
var MouseSync = $famous["famous/inputs/MouseSync"];
var TouchSync = $famous["famous/inputs/TouchSync"];
var GenericSync = $famous['famous/inputs/GenericSync'];
$scope.sync = new GenericSync(
["mouse", "touch"],
{direction: GenericSync.DIRECTION_X}
);
$scope.sync.on('update', function(data){
// do stuff while swiping
});
$scope.sync.on('end', function(data) {
// do stuff at swipe end
});
The above is all working fine. My problem now is that I have html inputs in some of the views which I cannot access/enter due to the above. The surfaces in which these are contained pipe their events to 'sync':
<fa-surface fa-pipe-to="sync">
<input type="text"></input>
</fa-surface>
I know that the issue here is that the click-event on my input is passed on to sync. I just don't know what to do about it. Any ideas?
Many thanks!
Did you try the HTML5 autofocus attribute <input type="text" autofocus></input> or setting the focus on click? <input type="text" ng-click="focus($event)"></input>
For the second option, you will need to set up a function on the scope as follows:
$scope.focus = function(ev){
ev.target.focus()
}

Knockout JS Using IF statement and With Statement listen for click event

The input field should be empty on page load.
When the user clicks the 'Edit Post' then I call KO click and 'select' function (all working) .. when I do this call the row selected is bound correctly.
Current code automatically binds on page load so the first record is in the input field.
<div data-bind="with: Selected">
<input type="text" data-bind="value: Name" />
</div>
<i title="Edit Post" data-bind="click: $parent.select"></i>
Example hack
<div data-bind="if **click: $parent.select then** with: Selected">
<input type="text" data-bind="value: Name" />
</div>
<i title="Edit Post" data-bind="click: $parent.select"></i>
How do I write a data-bind if 'click' then do 'with: Select' ?
Update
Add example code: http://jsfiddle.net/uC8Vt/70/
Generally you would just want this to work off of the Selected observable. If it is not populated, then it won't render the area. If it is pooulated, then whatever object that Selected holds will be used.
So, when you call $parent.select you would want to populate Selected with your object.
In fact, observables are functions, so unless you need to run other logic, you can even take a shortcut and bind your click directly against the Selected observable. The current data is passed as the first argument, which sets the value of the observable.
You would change the Selected property depending on the item clicked...
So an example viewModel might be like...
var items = [{ Name: 'item1' }, { Name: 'item2' }];
var viewModel = {
items: items,
Selected: ko.observable(items[0])
}
viewModel.select = function(selectedItem) {
// The first arg is the context of the item clicked
// Selected in an observable
viewModel.Selected(selectedItem);
};
Then, as Selected changes... your Name binding will automatically update.