I am checking some user input values if they are empty and if yes then I looping through their titles (textinput title) and checking if they contain '*'. If they do, I display a message to the user.
However, my approach isnt really working for some reasons. It just continues further even if the user doesnt fill out the required fields.
What am I doing wrong here?
for (i = 0; i < this.myInputFields.myTextFields.length; i++) {
data[this.myInputFields.myTextFields[i].key] = this.myInputFields.myTextFields[i].inputValues; //there is a bug here, if user doesnt fill the first textinput it will fail to send
if (this.myInputFields.myTextFields[i].inputValues === '') {
if (this.myInputFields.myTextFields[i].title.every('*')) {
return Alert.alert('Please fill out the required fields!')
}
}
}
If the user doesnt give an input in the first TextInput, that fails the operation and displays an error which says that 'this.myInputFields.myTextFields[i].key' is not defined. It is obviously failing because it is finding the array empty and in fact it expects there to a be a value. But how can I make it continue even that one is empty?
You are comparing the value of this.myInputFields.myTextFields[i].inputValues with '' explicitly. This will fail if inputValues is anything other than ''. (undefined for example)
...
if (this.myInputFields.myTextFields[i].inputValues === '')
...
instead, just check for falsiness:
...
if (!this.myInputFields.myTextFields[i].inputValues)
...
Related
When I have a textarea like
<textarea v-model="foo.abc.text"></textarea>
and either foo or foo.abc does not exist yet then
vue removes either parts of the DOM or is giving me a blank page.
It does never recover.
That alone is annoying, regardless of if I am using a debug version of vue or not.
If I try to use an approach that I have been advised to use earlier like
<textarea v-model="foo?.abc?.text"></textarea>
then I am still out of luck, I presume that I get a "rvalue" using those question marks and what I need rather is a variable location.
How do I, with as little trickery as possible, allow v-model to exist later on even if it doesnt exist now (late binding)?
Just shape your data accordingly and initialize it with empty values:
data(){
return {
foo: {
abc: {
text: ''
}
}
}
}
You can later populate it e.g. with the result of api call, but it's still better to initialize data properly
I would suggest going the :value + #input way. It allow more control over the input model, and does not require hiding it.
<textarea :value="!!foo && foo.abc.text" #input="(val) => !!foo && (foo.abc.text = val)" />
You can even hook in a validator:
<textarea
:value="!!foo && foo.abc.text"
#input="(val) => !!foo && (foo.abc.text = val)"
:rules="v => !v && 'The object has not been initialised'"
/>
I found a solution I can live with and then I got a comment in the same direction:
Conditionally showing the textarea.
v-if seems to do it but it falls under the "trickery" category, I think (angularjs would be more relaxed).
<textarea v-if="foo!=null" v-model="foo.abc"></textarea>
The symptom to hiding components if something is not all correct is not the best part of vue.js. Better show them and color them red.
Perhaps it's just a misunderstanding on my side, but I thought the callback for createGenericItem in the PeoplePicker (https://developer.microsoft.com/en-us/fabric#/components/peoplepicker) was used to handle input, that cannot be matched to any of the available items, and then give the possibility to create an adhoc item for this. But, whatever I tried, the callback is never called.
I made a simple pen here for the issue: https://codepen.io/anon/pen/daGPWe?editors=0010
In the example, there are two items, Peter and Maria. If you type something different (and hit enter, tab, space, whatever) I'd expect the createGenericItem callback to be called, but it isn't.
What am I doing wrong? Or is there a misunderstanding of the purpose of this callback? I'm unable to find an example anywhere.
Regarding
but I thought the callback for createGenericItem in the PeoplePicker
(https://developer.microsoft.com/en-us/fabric#/components/peoplepicker)
was used to handle input
that's correct. In order to trigger IBasePickerProps.createGenericItem function, IBasePickerProps.onValidateInput function needs to be provided with ValidationState.valid as a return value, for example:
<NormalPeoplePicker
createGenericItem={this.createGenericItem}
onValidateInput={this.handleValidateInput}
selectedItems={this.state.selectedItems}
onResolveSuggestions={this.handleResolveSuggestions}
onChange={this.handleChange}
/>
private handleValidateInput(input: string) {
return ValidationState.valid;
}
private createGenericItem(input: string, validationState: ValidationState) {
return { text: "Unknown person", state: validationState };
}
This demo demonstrates it, once tab or enter key is clicked and value cannot be resolved to any of the available items, Unknown person item is getting displayed
I have an input field for a value that should have exactly 5 digits. I would like to show errors when typing characters other than digits immediatly (onChange) but showing the error for unsufficient string length only on blur.
My rule looks like so at the moment:
ValidationRules
.ensure("myInput")
.matches(new RegExp(/[0-9]/))
.minLength(5)
.on(this);
MaxLength is restricted by setting maxlength in html.
If I set the validation trigger to "onChange" to get an immediate response to wrong characters I also get an error shown for not satisfying the minLength rule while typing correct digits until having typed 5 of them.
The behavior I would like to have is to apply the matches-rule onChange and the minLength-rule onBlur.
Is there any possibility to apply two rules on the same property on different events? I know how to validate manually but I don't know how to differenciate between rules.
You can use the when fluent API to satisfy your needs. Something like this -
ValidationRules
.ensure('email')
.email()
.required()
.when((order) => {
if (order.length > 4) {
order._ruleHasBeenMet = true;
}
return order.length > 4 && order._ruleHasBeenMet;
}
.withMessage('Email is required when shipment notifications have been requested.');
Encouraged by #PWKad's answer I played a little with .when() and came up with this:
I changed the validate trigger to "validateOnChangeAndBlur" and added a reference to my field:
<input type="text" value.bind="myInput & validateOnChangeAndBlur" maxlength="5" ref="myInputRef">
I extended the validation rule with a conditional validation checking if my input has focus as I only want to validate length when the input loses focus:
ValidationRules
.ensure("myInput")
.matches(new RegExp(/[0-9]/))
.minLength(5)
.when(() => this.dwKapitel !== document.activeElement)
.on(this);
This works like I expect it to work.
I have an edit page (in a DurandalJS single page app), where I use the .canDeactivate lifecycle method to check if there are any changes to the record, and optionally prompt them for confirmation before leaving the page.
I also have a 'Save' and 'View History' button. Is the correct thing to do to override the .canDeactivate method before calling router.navigate, to stop the modal popup invoking?
E.g.: As here:
self.onSave = function() {
self.repository.updateItem(self.model).done(function() {
self.canDeactivate = null; // Is this the correct way to do this?
router.navigate("#/home");
}
}
As this .canDeactivate will otherwise get called:
self.canDeactivate = function() {
if (!self.model.hasChanges()) {
return true;
}
return app.ShowMessage("Unsaved data will be lost", "Are you sure you wish to exit?", ["Yes", "No"]).done(function(result) {
return result !== "No";
}
};
Why dont you just set
self.model.hasChanges(false)
in your updateItem callback?
Then when your canDeactivate is called, it will return true.
Also you seem to have an error in your ShowMessage callback. I think you mean to do:
return result != "No";
I don't think the way Durandal decides whether to attempt to call a canDeactivate function is fully defined, other than the fact that if it's not in the view model, it won't try. Hence, even if it works as is, a future version of the framework could change its check to something like if (canDeactivate in viewModel) viewModel.canDeactivate(...); without further tests, and your code would break.
This is unlikely, but if you want to worry about it, you should thus delete self.canDeactivate instead of assigning it the null value.
Quote from the documentation:
To participate in the lifecycle, implement any (or none) of the
functions below on the object that you set the activator to (...)
Current implementation (activator.js, L126, 1eecbc2d3f84dc42eb7304bde761d88f300d8951):
if (item && item.canDeactivate) {
So it only checks if it's truthy (which would indicate using null works fine currently, too).
If you want to discuss the pattern, I don't see anything wrong with it, as long as it makes sense to you and everyone who should read the code.
You're not supposed to be activating and deactivating views programmatically in any critical path, so performance should be irrelevant either way (flag on view model or deletion of canDeactivate).
I am using extjs 4.1.1a for developing some application.
I had a form consisting of two combo-boxes and an item-selector.
Based on the value selected in first combo-box , the itemselector will load its data from database. This is working fine.
My problem is, if i reselect the first combo-box the new data will be displayed in itemselector along with previous data displayed in itemseletor .That is previous data displayed in itemselector will remain there itself.
for example: name "test1" consists of ids 801,2088,5000. on selecting test1 in firstcombobox itemselector must show output as below.
and if "test2" consists of ids 6090,5040. on selecting test2 in firstcombobox itemselector must show output as below.
problem is. for first time if i select "test1" from firstcombobox , output will come as expected. if i reselect "test2" from firstcombobox , output will come as below.
as you can see, previous data displayed (marked in red rectagle) remains there itself with new data displayed (marked with green rectangle).
I want for every reselection of first combobox, previously displayed data in itemselector to be erased before printing new data on itemselector.
How can I reset the itemselector for every reselection of first combobox?
You should remove all items from the store of the itemselector by the removeAll command. After that you should load the store of the itemselector.
itemselector.store.removeAll();
itemselector.store.load();
Any solutions above solve my problem.
i found solution from Sencha Forum.
https://www.sencha.com/forum/showthread.php?142276-closed-Ext-JS-4.0.2a-itemselector-not-reloading-the-store
in the itemselector.js file, change the line marked below.
populateFromStore: function(store) {
var fromStore = this.fromField.store;
// Flag set when the fromStore has been loaded
this.fromStorePopulated = true;
// THIS LINE BELOW MUST BE CHANGED!!!!!!!!!!!!
fromStore.loadData(store.getRange()); //fromStore.add(store.getRange());
// setValue waits for the from Store to be loaded
fromStore.fireEvent('load', fromStore);
},
You need to insert...
this.reset();
at the head of the function that is inserting the data.
As an example...
Ext.override( Ext.ux.ItemSelector, {
setValue: function(val) {
this.reset();
if (!val) return;
val = val instanceof Array ? val : val.split(this.delimiter);
var rec, i, id;
for (i = 0; i < val.length; i++) {
var vf = this.fromMultiselect.valueField;
id = val[i];
idx = this.toMultiselect.view.store.findBy(function(record){
return record.data[vf] == id;
});
if (idx != -1) continue;
idx = this.fromMultiselect.view.store.findBy(function(record){
return record.data[vf] == id;
});
rec = this.fromMultiselect.view.store.getAt(idx);
if (rec) {
this.toMultiselect.view.store.add(rec);
this.fromMultiselect.view.store.remove(rec);
}
}
}
});
are u got it?
when u select that combobox frist stoe of item selector is null after store load with ur pass the para meters
for example
store.load(null),
store.proxey.url='jso.php?id='+combobox.getrawvalue(),
store.load();
like that so when ur select a value in ur combobox that time ur used a listeners to ur combobox in that listners ur used above code , select ur some value in combobox that time frist store is get null after ur pass some values to json.php then store load with responce so that time old data is remove and new data load in that store
if u post ur code i will give correct code
I ran into the same issue with ExtJS 4.2.1. I got it to work by calling reload() on the data store and then setValue() with an empty string on the item selector in the data store's reload() callback.
Ext.create("Ext.form.field.ComboBox", {
// Other properties removed for brevity
listeners: {
change: function(field, newValue, oldValue, eOpts) {
Ext.getStore("ExampleStore").reload({
callback: function() {
Ext.getCmp("ExampleItemSelector").setValue("");
}
});
}
}
});
Ext.create("Ext.data.Store", {
storeId: "ExampleStore",
// Other properties removed for brevity
});
Ext.create("Ext.form.FormPanel", {
// Other properties removed for brevity
items:[{
xtype: "itemselector",
id: "ExampleItemSelector",
// Other properties removed for brevity
}]
});
For any folks that are curious, I'm fairly convinced there's a bug in the item selector's populateFromStore() function. When the function is called, it blindly adds all of the values from the bound store (store) to the internal store (fromStore). I suspect there should be a call to fromStore.removeAll() prior to the call to fromStore.add(). Here's the relevant code from ItemSelector.js.
populateFromStore: function(store) {
var fromStore = this.fromField.store;
// Flag set when the fromStore has been loaded
this.fromStorePopulated = true;
fromStore.add(store.getRange());
// setValue waits for the from Store to be loaded
fromStore.fireEvent('load', fromStore);
},
EDIT 12/18/2013
If you've configured any callback events on the item selector (e.g. change), you may want to disable the events temporarily when you call setValue(""). For example:
var selector = Ext.getCmp("ExampleItemSelector");
selector.suspendEvents();
selector.setValue("");
selector.resumeEvents();
I had the same problem and finally I decided to modify the extjs source code, not considering it a big issue as extjs itself its saying in the start of the file
Note that this control will most likely remain as an example, and not as a core Ext form
control. However, the API will be changing in a future release and so should not yet be
treated as a final, stable API at this time.
Based on that, as jstricker guessed (and sadly I didn't read and took me a while to arrive to the same conclusion), adding fromStore.removeAll() before fromStore.add() solves the problem.
Outside of the problem (but I think it can be interesting as well), additionally, I also added listConfig: me.listConfig in the MultiSelect configuration (inside createList), that way it's possible to format each item additional options (such as images, etc.) setting in the 'itemselector' the option listConfig as it's explained in the (irrealistic) documentation.
Need to reset the store used in ItemSelector that can be done by setting Empty object like below. Also need to call clearValue() method of ItemSelector component.
store.setData({});
ItemSelectorComponent.clearValue();