I can not return a value (RXJS) - javascript

I would to return a value, but I can not..
I do not know how I could do
The value that receives:
public filterOptions: Observable<string[]>;
My code that I would to return:
this.filterOptions = this.myForm.get('search').valueChanges.pipe(
startWith(null),
map((val) => {
if (!val) {
this.suscriptionSearch.unsubscribe();
return null;
}
if (this.bool) {
const filterValue = val.trim().toLowerCase();
const obj = {search: ''}
obj.search = filterValue;
this.suscriptionSearch = this.userService.searchUser(obj).subscribe((data)=>{
let monTab:string[] = [];
for (let index = 0; index < data.length; index++) {
monTab[index] = data[index].nom
}
return monTab.filter((option) => {
return option.toLowerCase().startsWith(filterValue)
}) //the value to return
});
}
}));

I found the solution .. I share it with you.
this.filterOptions = this.myForm.get('search').valueChanges.pipe(
startWith(null),
switchMap((val) => {
if (this.bool) {
const filterValue = val.trim().toLowerCase();
const obj = {search: ''}
obj.search = filterValue;
return this.userService.searchUser(obj).pipe(map((data)=>{
let monTab:string[] = [];
for (let index = 0; index < data.length; index++) {
monTab[index] = data[index].nom
}
console.log(monTab);
return monTab.filter((option) => {
return option.toLowerCase().startsWith(filterValue)
});
}))
} else {
return of(null);
}
}));

Related

rewrite an array of letters to numbers using dictionary

examples:
"heLLo" => 0.1.2.2.3
"javAscript" => 0.1.2.1.3.4.5.6.7.8
"hippopotomonstrosesQuippedaliophobia" => 0.1.2.2.3.2.3.4.3.5.3.6.7.4.8.3.7.9.7.10.11.1.2.2.9.12.13.14.1.3.2.0.3.15.1.13
my non-working code:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
var pipa = word.toLowerCase().split("")
for (i=0;i<pipa.length;i++) {
if (!dic.includes(pipa[i])) {
dic.push({key: count, value: pipa[i]});
count ++
}
for (j=0;j<pipa.length;j++) {
res.push(dic.key[pipa[i]])
}
return res.join(".");
}
Thanks in advance
To associate characters to numbers, don't use an array, use an object:
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return [...word]
.map(char => numbersByChar[char] ?? (numbersByChar[char] = i++))
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
Or without the concise syntax that you might find more readable
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return Array.from(word)
.map((char) => {
if (numbersByChar[char] === undefined) {
numbersByChar[char] = i;
i++;
}
return numbersByChar[char];
})
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
hint 1 is that you can get a letter like: word[index]
so change your code to this:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
for (i=0;i<word.length;i++) {
let dicItem = dic.find(x=>x.value==word[i]);
if(!dicItem) {
dic.push({key: count, value: word[i]});
res.push(count);
count ++;
}
else res.push(dicItem.key);
}
return res.join(".");
}

Function gets called before the subscribe call is completed in Angular

I am fetching datas from server but before the call gets completed the function gets called returning an empty array.I am new to RxJs could any one help me on it
getRows: (params) => {
setTimeout(() => {
const dataAfterSortingAndFiltering = this.sortAndFilter(audits.docs, params.sortModel, params.filterModel);
const rowsThisPage = dataAfterSortingAndFiltering.slice(0, audits.items.end);
let lastRow = -1;
if (dataAfterSortingAndFiltering.length <= params.endRow) {
lastRow = dataAfterSortingAndFiltering.length;
}
params.successCallback(rowsThisPage, lastRow);
}, 3000);
sortAndFilter function:
sortAndFilter(allOfTheData, sortModel, filterModel) {
return this.sortData(sortModel, this.filterData(filterModel, allOfTheData));
}
filterData function:
filterData(filterModel, data) {
const filterKeys = Object.keys(filterModel);
const filterPresent = filterModel && Object.keys(filterModel).length > 0;
if (!filterPresent) {
return data;
}
const resultOfFilter = [];
const filterParams = [];
for (let i = 0; i < filterKeys.length; i++) {
filterParams.push(`${filterKeys[i]}=${filterModel[filterKeys[i]].filter}`);
}
const params = filterParams.join('&');
this.auditService.getColumnSearch(params).pipe(first()).subscribe((datas: any) => {
resultOfFilter.push(...datas.docs);
});
return resultOfFilter;
}
SortData function:
sortData(sortModel, data) {
console.log('sortModel got called', sortModel);
console.log('data', data);
const sortPresent = sortModel && sortModel.length > 0;
if (!sortPresent) {
return data;
}
const resultOfSort = data.slice();
resultOfSort.sort((a, b) => {
for (let k = 0; k < sortModel.length; k++) {
const sortColModel = sortModel[k];
const valueA = a[sortColModel.colId];
const valueB = b[sortColModel.colId];
if (valueA == valueB) {
continue;
}
const sortDirection = sortColModel.sort === 'asc' ? 1 : -1;
if (valueA > valueB) {
return sortDirection;
} else {
return sortDirection * -1;
}
}
return 0;
});
return resultOfSort;
}
Before the server call gets completed the sortData function returns the data as [].
Leverage the feature of async and await
export class AuditComp {
getRows(params) {
setTimeout(() => {
const dataAfterSortingAndFiltering = this.sortAndFilter(audits.docs, params.sortModel, params.filterModel);
const rowsThisPage = dataAfterSortingAndFiltering.slice(0, audits.items.end);
let lastRow = -1;
if (dataAfterSortingAndFiltering.length <= params.endRow) {
lastRow = dataAfterSortingAndFiltering.length;
}
params.successCallback(rowsThisPage, lastRow);
}, 3000);
}
sortAndFilter(allOfTheData, sortModel, filterModel) {
return this.sortData(sortModel, this.filterData(filterModel, allOfTheData));
}
sortData(sortModel, data) {
console.log('sortModel got called', sortModel);
console.log('data', data);
const sortPresent = sortModel && sortModel.length > 0;
if (!sortPresent) {
return data;
}
const resultOfSort = data.slice();
resultOfSort.sort((a, b) => {
for (let k = 0; k < sortModel.length; k++) {
const sortColModel = sortModel[k];
const valueA = a[sortColModel.colId];
const valueB = b[sortColModel.colId];
if (valueA == valueB) {
continue;
}
const sortDirection = sortColModel.sort === 'asc' ? 1 : -1;
if (valueA > valueB) {
return sortDirection;
} else {
return sortDirection * -1;
}
}
return 0;
});
return resultOfSort;
}
async filterData(filterModel, data) {
const filterKeys = Object.keys(filterModel);
const filterPresent = filterModel && Object.keys(filterModel).length > 0;
if (!filterPresent) {
return data;
}
const resultOfFilter = [];
const filterParams = [];
for (let i = 0; i < filterKeys.length; i++) {
filterParams.push(`${filterKeys[i]}=${filterModel[filterKeys[i]].filter}`);
}
const params = filterParams.join('&');
await this.auditService.getColumnSearch(params).pipe(first()).toPromise()
.then((datas: any) => {
resultOfFilter.push(...datas.docs);
});
return resultOfFilter;
}
}
comment if faced any issue.

How to properly return value from a data inside the function

Im new to javascript and started to learn amazing stuff from it. As the code below how can I be able to return the value of index inside getData().then(data => {. getData function has json response values.
subPatternStart() {
getData().then(data => {
var patternStart = 1525750500000;
var index = 0;
for (var i = 0; i < data.length; i++) {
if ( patternStart >= data[i].time && patternStart < data[i+1].time ) {
//...somecode
}
}
console.log("Index:" , index);
})
}
What I want to achieve is that when I call this function I should ONLY get the value of index, which in this case the console log value is equivalent into 1.
I have this in my render method.
render() {
index={this.subPatternStart()}
}
In this simple code, it returns the exact value in the render method, and I want to do something like this.
subPatternStart() {
var patternStart = 1;
return patternStart;
}
You should set the state of the component with the value you get from getData. Then React can update it self and render the page. For example
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
index: 0
}
}
subPatternStart() {
getData().then(data => {
var patternStart = 1525750500000;
var index = 0;
for (var i = 0; i < data.length; i++) {
if (patternStart >= data[i].time && patternStart < data[i + 1].time) {
//...somecode
}
}
this.setState({
index: index
});
})
}
render() {
index = this.state.index
}
}
the function subPatternStart calls an async function getData so you need to use either callback or promises to get data in return.
1. Using Callbacks
subPatternStart(callbackFunction) {
getData().then(data => {
var patternStart = 1525750500000;
var index = 0;
for (var i = 0; i < data.length; i++) {
if (patternStart >= data[i].time && patternStart < data[i + 1].time) {
//...somecode
}
}
console.log("Index:", index);
callbackFunction(index);
})
}
// calling the function
render() {
var index;
this.subPatternStart((i) => { index = i })
}
2. Using Promises
subPatternStart(callbackFunction) {
var promise = new Promise(resolve => {
getData().then(data => {
var patternStart = 1525750500000;
var index = 0;
for (var i = 0; i < data.length; i++) {
if (patternStart >= data[i].time && patternStart < data[i + 1].time) {
//...somecode
}
}
console.log("Index:", index);
resolve(index);
})
})
return promise;
}
// calling the function
async render() {
index = await this.subPatternStart();
}

Filter letter by letter on Array Angular

I am trying to filter letter by letter on an array as below
MyJSON
"mainArr":[
{
"data":false,
"myArr":[
{
"myNumber": 12345,
},
{
"myNumber": 8961,
}
]
}
]
And here is code which I am drafting below for search but unable to pick object based on letter keypress or key down or ion-input
if (filterVal && filterVal.trim() !== '') {
this.myArray = this.myArray.filter(function (item) {
const results: any = [];
const obj = item.mainArr[0];
if (_.has(obj, 'myArr')) {
console.log(obj.myArr.indexOf(filterVal));
for (let i = 0; i < obj.myArr.length; i++) {
if (obj.myArr.indexOf(filterVal) !== -1)
return results.push(obj.myArr[i]);
}
}
}
});
}
Refered URL
Tried another way of implementing it, but backspace is not re-binding to original array
let results: any = [];
events.subscribe('filterSearch', (filterVal: string) => {
if (filterVal && filterVal.trim() !== '') {
results = Object.assign(this.allEventsSorted.filter(function (item: any): any {
const fltDty = item.mainArr[0];
if (_.has(fltDty, 'myArr')) {
return _.some(
item.mainArr[0].myArr,
function (tag): any {
return _.startsWith(tag.myNumber, filterVal);
// return _.includes(tag.myNumber, filterVal);
}
);
}
}));
this.allEventsSorted = results;
}
});

How to concatenate two NodeList objects into one, avoiding duplicates

I am writing a few functions to simplify my interaction with Javascript Nodes, here is the source-code so far:
Node.prototype.getClasses = function() {
return this.className ? this.className.split(" ") : "";
};
Node.prototype.hasClass = function(c) {
return this.getClasses().indexOf(c) >= 0;
};
Node.prototype.addClass = function(c) {
if (!this.hasClass(c)) {
this.className += " " + c;
}
return this;
};
Node.prototype.removeClass = function(c) {
if (this.hasClass(c)) {
var classes = this.getClasses();
var newClasses = [];
for (var index = 0; index < classes.length; index++) {
if (classes[index] !== c) {
newClasses.push(classes[index]);
}
}
this.className = newClasses.join(" ");
}
return this;
};
function NodeCollection(nodes) {
this.nodes = nodes;
this.addClass = (c) => {
for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
this.nodes[nodeIndex].addClass(c);
}
return this.nodes;
};
this.removeClass = (c) => {
for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
this.nodes[nodeIndex].removeClass(c);
}
return this.nodes;
};
this.getHTML = () => {
var output = "";
for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
output += this.nodes[nodeIndex].outerHTML;
}
return output;
};
this.each = (f) => {
for (var nodeIndex = 0; nodeIndex < this.nodes.length; nodeIndex++) {
f(this.nodes[nodeIndex]);
}
return this.nodes;
};
}
Node.prototype.query = function(s) {
return new NodeCollection(this.querySelectorAll(s));
};
Node.prototype.siblings = function(s) {
var rawSiblings = this.parentNode.querySelectorAll(s);
var output = [];
for (var siblingIndex = 0; siblingIndex < rawSiblings.length; siblingIndex++) {
if ((rawSiblings[siblingIndex].parentNode === this.parentNode) && (rawSiblings[siblingIndex] !== this)) {
output.push(rawSiblings[siblingIndex]);
}
}
return new NodeCollection(output);
};
Everything is working great and I am quite content with these functions, I have managed to prevent a lot of headaches without the usage of Javascript frameworks (a hobby project).
Now, I would like to be able to write a query function for NodeCollection as well, however, I am not quite aware of how should I concatenate the nodes members of the NodeCollection objects, which are instances of NodeList. I would like to write something like this as a member function of NodeCollection:
this.query = (s) => {
//create an empty NodeList
for (var index = 0; index < this.nodes.length; index++) {
//concat this[nodes][index] to the node list created outside the
//cycle avoiding possible duplicates
}
//return the concatenated NodeList
};
How can I achieve this?
How to concatenate two NodeList objects into one, avoiding duplicates
Use isSameNode and Array.from
Array.from( nodeList1 ).forEach( function( ele, index ){
var isDuplicate = Array.from( nodeList2 ).some( ( ele2 ) => ele.isSameNode(ele2) );
if ( !isDuplicate )
{
nodeList2[ nodeList2.length ] = ele;
}
})
Now nodeList2 has all the nodes from nodeList1 which are not duplicates.
Demo
var nodeList1 = Array.from( document.querySelectorAll(".a") );
var nodeList2 = Array.from( document.querySelectorAll(".b") );
console.log( "original length " + nodeList1.length, nodeList2.length );
nodeList1.forEach(function(ele, index) {
var isDuplicate = nodeList2.some( ele2 => ele.isSameNode(ele2));
//console.log( ele, isDuplicate );
if (!isDuplicate) {
nodeList2.push( ele );
}
});
console.log( "Final length " + nodeList1.length , nodeList2.length );
<div class="a b"></div>
<div class="a"></div>
<div class="b"></div>
<div class="a b"></div>

Categories