TextField Events - javascript

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

Related

How to check within an if else statement if an array contains a certain value

Woo first stackover flow post!
I'm trying to change a result depending on what "character" button is clicked.
So I start with a variable called: gendr = [];.
if the button named "marge" is clicked, the margeFunction will run, which pushes the value "female" inside the array.
If the button "Henry" is clicked, the henryFunction will run, which pushes the value "male" inside the array.
A later function contains an if else statement, where if the array contains the value male "male sentence appears."
else if the arrays value is female,
"female sentence appears."
function helloFunction() {
if(gendr[female]) {
document.getElementById ('traitText').innerHTML = "and says the word hello in every sentence she speaks";
} else {
document.getElementById ('traitText').innerHTML = "and says the world hello in every sentence he speaks"
}
}
I'm not exactly sure how to do this I just made a guess but I would like to know the correct way to do this! thanks in advance :)
gendr[female] won't work, as there is no female variable, and you don't want to access the female position in the array, instead, it sounds as if you want to get the last value of that array. That can be done with gendr[gendr.length - 1] . Now you want to check if that value is "female" and you can check that by comparing it (===).
However it is questionable wether you need an array at all, why not just keep a boolean (isFemale = false;)?
There are multiple ways to do what you are trying to achieve. The indexOf method is an effective way to check if an element exists in an array. Also, ECMAScript 2016 has a new method includes to check if an element exists inside an array.
Here's an example:
var gender = ['male', 'female'];
function checkInArray(genderArray) {
if(genderArray.indexOf('male') > -1) {
//do something
return 'male found';
} else {
//do something
return 'female found';
}
}
function checkInArray2(genderArray) {
return genderArray.includes('male');
}
console.log(checkInArray2(gender))
var array = [1,2,3,4,5];
array.includes(2); //true
array.includes(4); //true
array.includes(1, 2); //false (second parameter is the index position in this array at which to begin searching)
Check this out: https://playcode.io/373046
The HTML part of your question should look like this
<button onclick="helloFunction('female')">Marge</button>
<button onclick="helloFunction('male')">Henry</button>
The javascript then
function helloFunction(gendr) {
if(gendr=="female") ...
}
I believe your problem is more about parameter passing and it is not about arrays.

Not able to identify duplicate value in Javascript Array

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?

Angular get typed character from ngModel and replace it inside the input

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();
}
}

typescript remove object array through parent key

Lets say I have this variable
this.mylist.push([{key:{"test1":name,"test":desc,"hi i am a test":other,"none":type,"amount":0} }]);
This will be added to the array mylist
I want however on some condition to remove the current created list by deleting it through the unique key so
I want to splice the object array so the value will be removed to prevent duplicates
I tried
this.mylist.splice(this.mylist.indexOf(key), 1);
But did not work
i try to remove the array by getting the unique key which holds these child values
I also tried
this.mylist.splice(this.mylist.indexOf([{key}]), 1);
Someone who can help me out :(
CheckBox(values,values,values) {
this.bool = (this.mylist.indexOf(key) === -1);
if (this.bool) {
this.mylist.push([{key:{"key":key,"naam":naam,"beschrijving":beschrijving,"type":type,"aantal":aantal} }]);
}
else {
this.mylist.splice(this.mylist.indexOf(key), 1);
}
}
The function above is an event when a user clicks on a checkbox. When true the array must be filled with values. Else the array with the unique key must be removed to prevent duplicates
After the push statement, this.mylist will contain the array of arrays since you have pushed
[{key:{"test1":name,"test":desc,"hi i am a test":other,"none":type,"amount":0} }]
which is an array and you cannot access the array with the key (in this case you cannot access this.mylist[0], if the above array is added as first element, with this.mylist.indexOf(key))
One possible solution is you can make the type of mylist as object instead of array, then you can add elements to the Object like this
[{key:{"test1":name,"test":desc,"hi i am a test":other,"none":type,"amount":0} }];
this.mylist.key = {"test1":name,"test":desc,"hi i am a
test":other,"none":type,"amount":0} }
later you can use checkbox function like this
CheckBox(values) {
this.bool = (this.mylist.key === -1);
if (this.bool) {
this.mylist.key={"key":key,"naam":naam,"beschrijving":beschrijving,"type":type,"aantal":aantal};
} else {
delete this.mylist.key;
}
}
The logic behind Checkbox function seems incorrect, as the function will be checking if mylist contains a key, if it's not present then add the key to mylist and removes if its present. This logic does not properly handle the removing of duplicates if that's your final goal.

Angular2 bind ngModel from ngFor

So I'm rendering my textarea dynamically using ngFor however I'm not sure how I can pass the ngModel to bind it in my function.
<div *ngFor="let inputSearch of searchBoxCount; let i = index" [ngClass]="{'col-sm-3': swaggerParamLength=='3', 'col-sm-9': swaggerParamLength=='1'}">
<textarea name="{{inputSearch.name}}" id="{{inputSearch.name}}" rows="3" class="search-area-txt" attr.placeholder="Search Product {{inputSearch.name}}"
[(ngModel)]="inputSearch.name"></textarea>
</div>
textarea example:
textarea is render based on the length of the response I get from api call in my case searchBoxCount is basically searchBoxCount.length, so if it length is = 1 then it will only render 1 textarea if its 3 then it will show 3 textareas. The objs have different names (example: id/email/whatever), so ngModel is based on the obj name from the json object.
How do I bind inputSearch.name to my function getQueryString()
getQueryString() {
this.isLoading = true;
let idInputValue = inputSearch.name; //bind it here
return "?id=" + idInputValue
.split("\n") // Search values are separated by newline and put it in array collection.
.filter(function(str) {
return str !== ""
})
.join("&id=");
}
Search func where getQueryString() is called
searchProduct() {
let queryString1 = this.getQueryString();
this._searchService.getProduct(queryString1)
.subscribe(data => {
console.log(data);
});
}
I know how to do it if the ngModel is not coming from the ngFor, is there another way to get the value from the textarea without ngModel? maybe that's the only way or if I can still use ngModel.
Summary of current state
First, let me summarize where your data is. You have a list of one or more objects named searchBoxCount. Each of the elements in the list is an object which has a name property, so you could, for example, call let name = this.searchBoxCount[0].name; to get the name of the first object in the list.
In the HTML template you use ngFor to loop through all of the objects in the searchBoxCount list, and in each iteration you assign the object to a local (to the ngFor) variable named inputSearch. You then bind the input from the textarea created in each loop iteration to the name property for that iteration's inputSearch object.
How to get your data
The key here is that the inputSearch is the same Object as is stored in searchBoxCount at some particular index (index 0 for the first object, etc...). So when the ngModel is tied to inputSearch.name it is also bout to searchBoxCount[n].name. External to the ngFor, you would loop through the searchBoxCount list to get each name you need.
As a consequence
Based on the comments on the original post, it sounds like you can have one or
more names that you need to include in the query string output. That means for your getQueryString() to work, you have to loop through the list (or as in this case, let the list loop for us):
getQueryString() {
this.isLoading = true;
let result : string = "?id=";
this.searchBoxCount.forEach(
(inputSearch:any) => { //Not the same variable, but same objects as in the ngFor
result = result + inputSearch.name + "&id=";
});
result = result.slice(0, result.length - 4); //trim off the last &id=
return result;
}
Edit: Multiple different fields with different names
From the comments on this post, it now is clear each inputSearch has its own key to be used in the query string, that is stored in the name property. You need to preserve that name, which means you can't bind the ngModel to it. Otherwise the user will destroy the name by typing in their own text and there will be no way to get the correct key back. To that end, you need to store bind the ngModel to some other property of the inputSearch object. I am going to assume the object has a value property, so it looks like this:
{
name: "id",
value: "33\n44"
}
That is, each inputSearch has a name, and the value will have one or more values, separated by new line. You would then have to change the HTML template to this:
<div *ngFor="let inputSearch of searchBoxCount; let i = index"
[ngClass]="{'col-sm-3': swaggerParamLength=='3', 'col-sm-9':
swaggerParamLength=='1'}">
<textarea name="{{inputSearch.name}}"
id="{{inputSearch.name}}" rows="3" class="search-area-txt"
attr.placeholder="Search Product {{inputSearch.name}}"
[(ngModel)]="inputSearch.value"></textarea>
</div>
Notice that I changed the ngModel from inputSearch.name to inputSearch?.value (the ? allows for null if there is no value to begin with) inputSearch.value. The getQueryString() method then looks something like this:
getQueryString() {
let result:string = "?";
//for each of the input search terms...
this.searchBoxCount.forEach( (inputSearch:any) => {
// first reparse the input values to individual key value pairs
let inputValues:string = inputSearch.value.split("\n")
.filter(function(str) { return str !== "" })
.join("&" + inputSearch.name + "=");
// then add it to the overall query string for all searches
result = result +
inputSearch.name +
"=" +
inputValues +
"&"
});
// remove trailing '&'
result = result.slice(0, result.length - 1);
return result;
}
Note, using RxJs this is probably easier but I am testing vanilla javascript.
Using this, if the user entered two IDs (33 and 44), a single sku, and two emails, the result would be ?id=33&id=24&sku=abc123&email=name#compa.ny&email=an.other#compa.ny

Categories