I'm need to verify that entered text im my TextField is an email. I'm usually using Form Group to do this. In my Form Control property im using "updateOn: 'blur'. But I have problem if I have only 1 TextField in current view. It seems like (blur) is not called.
I'm do this in few other places in my app but only there it don't work. Only difference is that there is only one TextField in component, and in others is few more (2-5).
'''''HTML
<TextField id="field" class="input" hint="E-mail" keyboardType="email" returnKeyType="done" formControlName="email" #emailQ [ngClass]="{niepoprawne: !emailQValid}" (returnPress)="wyslij()"></TextField>
<Button text="Wyślij" class="button" (tap)="wyslij()"></Button>
'''''''TS
export class ZapomnialemComponent implements OnInit {
form: FormGroup;
#ViewChild('emailQ', { static: false }) emailQRef: ElementRef<TextField>;
emailQValid: boolean = true;
wyslanePrzyp: boolean = false;
constructor() {
}
ngOnInit() {
this.form = new FormGroup({
email: new FormControl(null, { updateOn: 'blur', validators: [Validators.required, Validators.email] })
});
this.form.get('email').statusChanges.subscribe(status => {
this.emailQValid = status === 'VALID';
});
}
wyslij()
{
if(!this.form.valid)
{
this.displayAlertDialog("Wprowadź poprawny adres e-mail")
return;
}
this.wyslanePrzyp = true;
}
You have only one text field in your form and have set updateOn to blur. Your text field will not hit blur unless you change the focus to next field Or programatically remove focus from the text field.
Related
I am facing issue with cypress in my project. I am having an input which is appear on click of search icon and disappear on blue event of the input.
I am writing cypress test to check my functionality, here I am facing a problem whenever I type in input with cypress .type() method but it is firing blur event of the input every time.
Once blur event is fired my input ill disappear from the DOM.
It will works fine if I remove autofocus from input.
Please can someone help me to write proper cypress test for my use case. Thank you.
component.ts
export class SearchTable {
private searchInput: HTMLInputElement;
#State() isSearchOpen: boolean = false;
private handleClickSearch = () => {
this.isSearch = !this.isSearch;
setTimeout(() => {
this.searchInput.focus();
})
}
handleBlur = () => {
console.log('blur event called!!!')
this.isSearch = !this.isSearch;
}
render() {
return (
<div slot="right-panel" data-test-id={`${this.dataTestId}-right-panel-slot`}>
{this.isSearch ?
<input data-test-id="input-search" onBlur={this.handleBlur} ref={el => (this.searchInput = el as HTMLInputElement)}/> :
<icon-component onClick={this.handleClickSearch} dataTestId={`${this.dataTestId}-search-icon`} icon="search" />
}
</div>
)
}
cypress test
it.only("check search functionality with empty data", () => {
cy.getSearchSection()
.find("icon-component").click()
.getSearchSection()
.findAllByTestId(`input-search`)
.type('volume4444')
.wait(600)
.should('have.value', 'volume4444');
});
I wanted to give some form visual validation cues, so I tried using class binding to do just that. If I use the ternary inline, it doesn't really meet my requirements of what should happen, but when I tried using computed prop, it made all the other components disappear.
If i tried doing it like this: v-bind:class="[(!validation.hasError('form.fullName'))?'has-success':'has-danger noValid']"
It just triggers the animation and the classes once and they stays there. I want to trigger the noValid animation everytime the user clicks my submit button if there's errors in validation.
I'm using simple-vue-validator btw.
Here's the godforsaken component, I use vue now-ui-kit template from Creative Tim as a base and customize my way from there. This is their Form Group Input component, docs here
<fg-input
class="input-lg"
:label="validation.firstError('form.fullName')"
placeholder="Full Name..."
v-model="form.fullName"
addon-left-icon="now-ui-icons users_circle-08"
v-bind:class="{ visualValidation }"
></fg-input>
Button Component: bootstrap-vue, cause their customized button doesn't really serve my purpose
<b-button type="submit" block pill variant="info" #click="submit">Submit Form</b-button>
My computation: noValid is the shaking animation class, has-success and has-danger just changes their appearances.
computed: {
visualValidation: function() {
const successClass = "has-success";
const errorBoi = "has-danger";
const shakeBoi = "noValid";
if (validation.firstError("form.fullName")) {
return errorBoi + " " + shakeBoi;
} else if (!validation.hasError("form.fullName")) {
return successClass;
}
}
}
I thought the variables that i returned would be binded as classes to the form.fullName Model but it's not doing anything, better yet, it made all my other components not rendering.
What should i do here? i'm just starting to learn Vue.js so i don't really understand what's going on here.
Edit from here:
I rewrote the logic to my class binding, and just use method to remove the class on click the components.
here is the updated component:
<fg-input
class="input-lg"
:label="validation.firstError('form.email')"
placeholder="Email Here..."
v-model="form.email"
addon-left-icon="now-ui-icons ui-1_email-85"
v-bind:class=" {'has-success' : isSuccEmail, 'has-danger' : isFailEmail, 'noValid': validNoEmail} "
#click="removeShake()"
></fg-input>
data:
isSuccEmail: false,
isFailEmail: false,
validNoEmail: false
method:
removeShake: function() {
let vm = this;
vm.validNoName = false;
vm.validNoEmail = false;
console.log(vm.validNoEmail);
console.log(vm.validNoName);
},
However, there's currently a bug, where the validator don't validate separately. It gave the class has-success to email even though it was full-name that was successful.
valEmail: function() {
let vm = this;
vm.$validate("form.email").then(function(success) {
if (success) {
vm.isFailEmail = false;
vm.isSuccEmail = true;
} else if (!success) {
vm.isSuccEmail = false;
vm.isFailEmail = true;
vm.validNoEmail = true;
} else {
alert("Fatal Error");
}
});
},
valName: function() {
let vm = this;
vm.$validate("form.fullName").then(function(success) {
if (success) {
vm.isFailName = false;
vm.isSuccName = true;
} else if (!success) {
vm.isSuccName = false;
vm.isFailName = true;
vm.validNoName = true;
console.log(vm);
} else {
alert("Fatal Error");
}
});
}
The $validate is a function of simple-vue-validator, the docs.
Submit function is just calling those two functions above.
I think this because of the promise call, is there a way to call the $validate() without promise?
There are a few problems here.
Firstly, while templates don't require you to use this. you still need to use it within your JS code. You should be seeing an error in the console, or maybe even at compile time depending on how you have linting configured.
if (validation.firstError("form.fullName")) {
What is validation? I assume that should be this.validation. Likewise a couple of lines further down.
Your next problem is here:
v-bind:class="{ visualValidation }"
The braces here are creating an object literal, so it's equivalent to this:
v-bind:class="{ visualValidation: visualValidation }"
This will be conditionally adding the string 'visualValidation' as a class , which isn't what you want. Get rid of the braces:
v-bind:class="visualValidation"
I have a problem with persisting user's data in a react-native application I am currently working on with my team. We have an app with a list of events and when you click on an event, it opens up the event details page and shows a menu to choose yes/no/maybe (attendance menu) which the user can toggle to select whether or not they are attending the event. Our code looks like this:
import React from 'react';
import { AsyncStorage, Text, View, StyleSheet, Picker } from 'react-native';
export class PickerMenu extends React.Component {
state = { choice: '' }
componentDidMount = () => AsyncStorage.getItem('choice').then((value) => this.setState({ 'choice': value }))
setName = (value) => {
AsyncStorage.setItem('choice', value);
this.setState({ 'choice': value });
}
render() {
return (
<View>
<Picker selectedValue = {this.state.choice} onValueChange = {this.setName} itemStyle = {styles.item}>
<Picker.Item label = "Yes" value = "yes" />
<Picker.Item label = "Maybe" value = "maybe" />
<Picker.Item label = "No" value = "no" />
</Picker>
</View>
);
}
}
We are running the build on Xcode. We want the user's choice to still be present after the page has been refreshed or the app has closed - this works HOWEVER,the choice that the user has selected, stays the same for every event. E.g. if they select 'Maybe' for event 1, the selection 'maybe' is highlighted for every other event in our app.
We had an idea of grabbing unique event IDs and implementing this into the AsyncStorage function but we are unsure of how to do this.
Any help will be great and much appreciated - thank-you!
In this case you need to use the async/await to store at the async storage
like this:
setName = async (value) => {
await AsyncStorage.setItem('choice', value);
this.setState({ 'choice': value });
}
Hope i have helped!
Some useful links for you:
https://facebook.github.io/react-native/docs/asyncstorage.html
I am trying to create some customer formatting on a field (to reproduce a masked text box functionality).
I have an observable and I am capturing the propertyChange Event. My question is: Can I modify the value of the observed property inside the event handler without entering in an infinite loop?
Here is my code:
model.customer.addEventListener(Observable.propertyChangeEvent, function(data) {
if (data.propertyName.toString() === 'homePhone') {
//Here is where I would like to change the value without triggering the event again
//The below code does not seem to be working
data.value = formatPhone(data.value);
}
});
I looked at https://github.com/bthurlow/nativescript-maskedinput, but unfortunately this module does not support databinding.
Thank you. Appreciate your help.
I have tested nativescript-maskedinput in a sample application and I was able to bind text property of this custom view. In regard to that if you add addEventListener and want to update for example TextField text property manually I think that property won't be updated properly. In addition I am attaching some sample code.
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:mi="nativescript-maskedinput" navigatingTo="navigatingTo">
<StackLayout>
<Label text="Tap the button" class="title"/>
<mi:MaskedInput mask="1-999-999-9999? x999" hint="1-555-555-5555" text="{{ masktext }}" placeholder="#" />
<Button text="tapToView" tap="onTap" />
</StackLayout>
</Page>
main-page.js
var observable_1 = require("data/observable"); // Event handler for Page "navigatingTo" event attached in main-page.xml
var newObservable = new observable_1.Observable();
function navigatingTo(args) {
// Get the event sender
var page = args.object;
newObservable.set('masktext', '');
page.bindingContext = newObservable;
}
exports.navigatingTo = navigatingTo;
function onTap(args) {
var newvalue = newObservable.get('masktext');
console.log('newValueget + ' + newvalue);
}
exports.onTap = onTap;
I am not sure if it is possible to override the getter, but if it is not possible you can do this:
function isPhoneFormatted(phone) {
//your algorithm wich return true or false
}
model.customer.addEventListener(Observable.propertyChangeEvent, function(data) {
if (data.propertyName.toString() === 'homePhone') {
//Here is where I would like to change the value without triggering the event again
//The below code does not seem to be working
if (!isPhoneFormatted(data.value)) {
data.value = formatPhone(data.value);
}
}
});
Notice that it is not well tested!
I have the following input control:
<input type="ng-model="someValue" ng-disabled="shouldBeDisabled"/>
and a model with following variables:
someValue - the value that should be displayed in INPUT when shouldBeDisabled==fals
shouldBeDisabled - if the INPUT should be disabled
disabledText - the text that should be displays in INPUT instead of someValue when shouldBeDisabled==true
How should I change the above HTML slipet to implement this with AngularJS?
Is it possible to implement this with build-in AngularJS directives with just these three model variables? Or do I need to introduce another variables (such as someValueForInputBox) and take care to synchonizing it with someValue (when not disabled) or disabledText (when disabled)?
You can do this by the following though you might want to put a watch on shouldBeDisabled;
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.shouldBeDisabled = true;
$scope.toggleIt = function() {
$scope.shouldBeDisabled= ! $scope.shouldBeDisabled;
$scope.someValue= $scope.shouldBeDisabled && $scope.disabledText || "true value"; // modify as required or leave off the true part.
}
});
You could also store the value so when the disabled text comes up and then toggles back you can repopulate it. Here it is with a watch.
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.shouldBeDisabled = true;
$scope.disabledText = 'disabled stuff';
$scope.maintainTrueValue = '';
$scope.$watch('shouldBeDisabled', function() {
if ($scope.shouldBeDisabled)
$scope.maintainTrueValue = $scope.someValue;
$scope.someValue= $scope.shouldBeDisabled && $scope.disabledText || $scope.maintainTrueValue;
});
$scope.toggleIt = function() {
$scope.shouldBeDisabled= ! $scope.shouldBeDisabled;
}
});
Demo with watch: http://plnkr.co/edit/8KAJc9JXvi2rffsjPXF5?p=preview
You could use ng-show/ng-hide to swap out the input like so:
<input ng-model="disabledText" ng-show="shouldBeDisabled" disabled/>
<input ng-model="someValue" ng-hide="shouldBeDisabled"/>
Here is a fiddle: http://jsfiddle.net/SVxCe/