Hi I have input(inside ngFor, so same input field created with length of my array) in my HTML and binding to my ngModel and i have ngModelChange function as below:
onChangeReference(value: any, account: any, option: any) {
// this.referenceArray = Object.keys(this.your_reference).map(key => this.your_reference[key]);
console.log(this.referenceArray, value, 'huhu');
let tmpReference:Array<any> = [];
if (value) {
if (_.includes(this.referenceArray, value)) {
console.log('item und');
option.isRefDuplicate = true;
// this.referenceArray.pop();
} else {
console.log('item illa');
this.referenceArray.push(value);
option.isRefDuplicate = false;
}
}
}
Basically what i need to achieve is if there is any duplicated value in this.your_reference Array, i need to show error below that particular input field. I could able to achive it 90%, but now the problem is if enter "aaa" in one input field, and in other input field i key in the same value "aaa", working fine. showing error message. But when i backspace and remove one value its actually a new value "aa" which shouldnt be in my this.your_reference array. But it still showing error. How to fix this guys. Any idea?
Related
context: Angular applications using the ngx-select-dropdown. A user can select multiple values, these values get sorted into "buckets" and sent to the api.
Issue: I am unable to remove a selected item from the end array - this.filterState. I have added a check to ensure that an item cant be added more than once - a click to select the item and a click to deselect the item. I thought that this would be a good time to remove the item with a splice as the user would have clicked to deselect if it already exists in the array - however, the dropdown does not pass the value of a deselected object it just removes it from the value array of the dropdown.
const index = this.filterState[convertedParam].indexOf(value);
if (index === -1) {
this.filterState[convertedParam].push(value);
}
Proposed solution: I think it will need some sort of comparison upon event change against the dropdown value object and the array that was previously sent to the api.
End goal: To be able to add and remove objects from the sorted array
Here is a stackblitz that I put together...
app.component.ts
handleFilterChange(prop: string, value: any): void {
// I think the comparison with "value" and whats already in "this.filterState" will need to be done here?
let field = this.fields.find(f => f.name === prop);
if (field.params) {
value.forEach(v => this.setFilterState(v.type, v, field));
} else {
this.setFilterState(prop, value, field);
}
console.log("SUBMITTED SORTED VALUES", this.filterState);
}
setFilterState(prop: string, value: any, field: Field): void {
const colourParamMap = {
I_am_RED: "reds",
I_am_BLUE: "blues",
I_am_GREEN: "greens"
};
if (field.name === "multiselect_1") {
const convertedParam = colourParamMap[prop];
const index = this.filterState[convertedParam].indexOf(value);
//stops from adding same value again and adds value to array
if (index === -1) {
this.filterState[convertedParam].push(value);
}
} else {
//There will be more logic here
this.filterState[prop] = value;
}
}
https://stackblitz.com/edit/ngx-select-dropdown-xkfbyr?file=app%2Fapp.component.ts
A simple fix in the end - I was trying to over complicate things. I needed to reset the this.filterState as the value from the dropdown will include every value from before, minus the ones that were deselected.
handleFilterChange(prop: string, value: any): void {
this.filterState = {
reds: [],
blues: [],
greens: []
};
I'm beginner with React JS and I'm doing a test project to train my skills.
I have a list of farms being rendered on the screen. The user can click on the button to register a new farm or can click on the property to be able to edit the existing property.
In a single Dialog Modal I do both. The problem is when I try to edit the Input field, it is not working. It doesn't matter what I type and nothing happens.
That's my input field, I'm using TextField from React Material:
<TextField
id="farmer-name"
label="Farm Name"
value={propertyData.farmerName}
onChange={(event) =>
changeField("farmerName", propertyData.id, event.target.value)
}
className={classes.input}
InputProps={{
className: classes.inputContent
}}
InputLabelProps={{
className: classes.inputLabel
}}
/>
And here's my function that will be able update my data:
const changeField = (field, id, value) => {
const newPropertyData = { ...propertyData };
if (newPropertyData.id === id) {
newPropertyData.field = value;
}
};
Here's my code, I put in CodeSandBox: https://codesandbox.io/s/spring-breeze-xnv3r?file=/src/index.js
Screen of my application
Can someone help me to edit that´s values? Thanks
You should save state on change in text field
const changeField = (field, id, value) => {
const newPropertyData = { ...propertyData };
if (newPropertyData.id === id) {
// change field value for specific id
newPropertyData[field] = value;
}
// set updated field value into state to show on form
setPropertyData(newPropertyData);
};
You are not actually changing the propertyData stored in the useState hook.
Currently, there will be a new property added called field in the newPropertyData object. However, this variable is never used or stored and you probably don't want the value to be stored in the field property.
The shortest answer is to pass a function to the setPropertyData which will receive the previous value of propertyData.
The previous propertyData can be extended with a dynamic property by using the following syntax: [field]: value.
const changeField = (field, id, value) => {
if (propertyData.id === id) {
setPropertyData(data => ({ ...data, [field]: value }));
}
};
How is it possible to get the new typed character (not the whole new value of the ngModel) then apply logic on it, then returning a new value for the ngModel ?
Example: let's say when a user types inside an input we want to take the new character he types then change it to something and append it to the previous value of the ngModel. Tried keypress and onModelChange but didn't seem to work
<ion-textarea #chat_input
(ngModelChange)="modelChanged($event)"
placeholder="Text Input"
[ngModel]="editorMsg"
(keyup.enter)="sendMsg()"
(ionFocus)="onFocus()">
</ion-textarea>
And My method is like:
modelChanged(e){
// e is the new value of editorMsg and not the new typed character, if I get the new character I can do
this.editorMsg+=e;
}
But I get only the new typed value from modelChange how can I get only the new typed character ?
I believe what you’re looking for is the keyup event.
You could have something like
<input (keyup)="onKey($event)">
And then in your component
onKey(event: any) {
console.log(event.key)
}
The important bit here is to use the event.key and not event.target.value. If you used the latter one it would always give you the input value instead of the input key
You can get more information for what you need here, where I got the relevant bit from
You can do the following:
modelChanged(e){
let lastChar;
if (e.length) {
lastChar = e[e.length -1]; // this gets the last character of the srting..
// do you logic with lastChar..
}
}
It works using (ngModelChange). See this StackBlitz
component.html
<input [ngModel]="name" (keypress)="onKeypress($event)">
component.ts
export class AppComponent {
name = 'try me';
onKeypress(event: KeyboardEvent) {
console.log(event);
// Do what you want...
this.name = event.key;
event.preventDefault();
}
}
I have an input v-model and I want to filter through a product list.
Here is my filter. The problem is that it only works if the item name matches the input exactly. How can I modify the filter to see any partial matches as the input is being typed?
Vue.filter('byName', function (data, input) {
if(input){
return data.filter(function (item) {
return item.name == input
});
}
return data
});
If you want to see "live" results, then you need to code your filter so that it returns items that partially match.
The simplest way is to use the startsWith() method. The following filter uses startsWith() to match all items that start with the input:
Vue.filter('byName', function (data, input) {
if(input){
return data.filter(function (item) {
// we check if the item's name starts with the input
return item.name.startsWith(input);
});
}
return data
});
Here is a JSFiddle of that filter in action.
On the other hand, if you wanted to return items that match anywhere, not just ones that started with the input, you can use String.prototype.indexOf().
To do this, replace
// we check if the item's name starts with the input
return item.name.startsWith(input);
with
// we check if the item's name contains the input as a substring
return item.name.indexOf(input) > -1;
I want to update an array through a textfield change.
For example, textfield contain he string = "ABC" and the array to be updated is {"ABC","DEF","GHI"}.
I wrote the following function in angularJS:
$scope.aliasChanged = function(newVal,oldFieldValue)
{
if($scope.ConfigJSON)
{
if($scope.ConfigJSON.LogProcessing.Fields.indexOf(oldFieldValue) > -1)
{
$scope.ConfigJSON.LogProcessing.Fields.splice($scope.ConfigJSON.LogProcessing.Fields.indexOf(oldFieldValue),1);
$scope.ConfigJSON.LogProcessing.Fields.push(newVal)
}
}
}
Corresponding html:
<input type="text" ng-model="row.alias"
ng-focus='oldFieldValue=row.alias'
ng-change="aliasChanged(row.alias,oldFieldValue)">
Now if there's a single edit(just one key press, everything works fine). "ABC" is removed from the array and "AB" is added. But if multiple keystrokes are logged in at a time, the code breaks. "ABC" is removed "AB" is added. But "AB" is not removed and "A" is not added. I guess the array was under write-lock by the first fucntion call when 'C' was being deleted. ANy clues how to achieve my target ?
Can you switch your array to an object instead? That way you can look up the property and change its value for each keystroke.
$scope.aliasChanged = function(key,newValue)
{
if($scope.ConfigJSON)
{
if($scope.ConfigJSON.LogProcessing.Fields[key])
{
$scope.ConfigJSON.LogProcessing.Fields[key] = newValue;
//$scope.ConfigJSON.LogProcessing.Fields.splice($scope.ConfigJSON.LogProcessing.Fields.indexOf(oldFieldValue),1);
//$scope.ConfigJSON.LogProcessing.Fields.push(newVal)
}
}
}
And the call in the html would look like:
<input type="text" ng-model="row.alias"
ng-change="aliasChanged('ABC', row.alias)">
You could always convert this object back into an array format if you really need an array when you submit the form (or whatever action you are doing afterwards).
http://plnkr.co/edit/o59oJgxpBIklag0Vca5e?p=preview