How to search inside an array property of an index - vue.js

I have to retrieve a list of apps that have certain string inside of an array property:
const users = algoliaClient.initIndex('apps')
return users.search('myId123', { hitsPerPage: 50 });
The apps objects are just like this:
{categories: ['an', 'interesting', 'category']}
How can I search the index for items with a categories property that contains any item in an array of strings?

const search = ["cat1", "cat2", "cat3"];
const apps = [
{
name: "app1",
categories: ["cat1", "cat5"],
},
{
name: "app2",
categories: ["cat2", "cat4"],
},
];
is that what you mean ? if so :
var myIndexes = [];
apps.forEach((app, index) => {
search.every((search) => {
if (app.categories.includes(search)) {
myIndexes.push(index);
return false; // return false here is for stoping the EVERY loop
} else {
return true; // keep running the EVERY loop
}
});
});

Related

How to refresh view when vuex store changes?

I get the data from the store like so
computed: {
notes() {
var data = this.$store.getters.getNotes;
var key = this.$store.getters.getTitleFilter;
if (key === "all") return data;
return data.filter((note) => {
var filteredNote = note.category.some(({ name }) => name === key);
if (filteredNote) return filteredNote;
});
},
},
When the note array changes (an item is removed, getNotes should reflect that. In other instances (where the data is returned without filtering) this used to do the trick:
watch: {
notes(newval) {
return newval;
},
},
I there a way to get the filtered array to update?

Detox get length of element

Hi i'm using detox and i would like to know how can I get the number of matches to
one element(length).
For example "card" match three times, how can I get the three.
const z = await element(by.id("card"))
https://github.com/wix/Detox/blob/master/docs/APIRef.Expect.md
https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md
They don't support it in the API /:
z output:
Element {
_invocationManager: InvocationManager {
executionHandler: Client {
isConnected: true,
configuration: [Object],
ws: [AsyncWebSocket],
slowInvocationStatusHandler: null,
slowInvocationTimeout: undefined,
successfulTestRun: true,
pandingAppCrash: undefined
}
},
matcher: Matcher { predicate: { type: 'id', value: 'card' } }
}
A workaround could be
async function getMatchesLength(elID) {
let index = 0;
try {
while (true) {
await expect(element(by.id(elID)).atIndex(index)).toExist();
index++;
}
} catch (error) {
console.log('find ', index, 'matches');
}
return index;
}
then you can use
const length = await getMatchesLength('card');
jestExpect(length).toBe(3);
Here is my solution in typescript:
async function elementCount(matcher: Detox.NativeMatcher) {
const attributes = await element(matcher).getAttributes();
// If the query matches multiple elements, the attributes of all matched elements is returned as an array of objects under the elements key.
https://wix.github.io/Detox/docs/api/actions-on-element/#getattributes
if ("elements" in attributes) {
return attributes.elements.length;
} else {
return 1;
}
}
Then you can use it like this:
const jestExpect = require("expect");
jestExpect(await elementCount(by.id("some-id"))).toBe(2);

Duplicate items in list after an API update

I'm learning vuejs and I'm doing a weather app, the goal is to rank cities with an index (humidex). I fetch weather information by API (axios) in order to collect data from several cities. I want to auto update data every x minutes, problem : some of my results are duplicated (the new data don't replace the old one).
I tried to set an unique key (based on latitude and longitude) for each item, it works for several results but not for all.
data () {
return {
items:[],
show: false,
cities: cities,
newCity:''
}
},
components: {
Item
},
computed: {
sortHumidex() {
return this.items.slice().sort((a,b) => {
return this.getHumidex(b) - this.getHumidex(a) || b.current.temp_c - a.current.temp_c
})
}
},
methods: {
addCity() {
if (this.newCity.trim().length == 0) {
return
}
this.cities.push(this.newCity)
this.newCity = ''
},
getHumidex: (el) => {
const e = 6.112 * Math.pow(10,(7.5*el.current.temp_c/(237.7+el.current.temp_c)))
*(el.current.humidity/100)
return Math.round(el.current.temp_c + 5/9 * (e-10))
},
indexGeo: (e) => {
const lat = Math.round(Math.abs(e.location.lat))
const lon = Math.round(Math.abs(e.location.lon))
return lat.toString() + lon.toString()
},
getApi: function () {
const promises = [];
this.cities.forEach(function(element){
const myUrl = apiUrl+element;
promises.push(axios.get(myUrl))
});
let self = this;
axios
.all(promises)
.then(axios.spread((...responses) => {
responses.forEach(res => self.items.push(res.data))
}))
.catch(error => console.log(error));
}
},
created() {
this.getApi()
this.show = true
}
}
The render when I update API :
By pushing to the existing array of items, you have to deal with the possibility of duplicates. This can be eliminated simply by replacing items every time the API call is made.
Replace:
responses.forEach(res => self.items.push(res.data))
with:
self.items = responses.map(res => res.data)

Wait until API fully loads before running next function -- async/await -- will this work?

I am a beginner with Javascript with a bit of knowledge of VueJs. I have an array called tickets. I also have a data api returning two different data objects (tickets and user profiles).
The tickets have user ids and the user profiles has the ids with names.
I needed to create a method that looks at both of that data, loops through it, and assigns the full name of the user to the view.
I was having an issue where my tickets object were not finished loading and it was sometimes causing an error like firstname is undefined. So, i thought I'd try and write an async/await approach to wait until the tickets have fully loaded.
Although my code works, it just doesn't "feel right" and I am not sure how reliable it will be once the application gets larger.
Can I get another set of eyes as to confirmation that my current approach is OK? Thanks!
data() {
return {
isBusy: true,
tickets: [],
userProfiles: [],
}
},
created() {
this.getUserProfiles()
this.getTickets()
},
methods: {
getUserProfiles: function() {
ApiService.getUserProfiles().then(response => {
this.userProfiles = response.data
})
},
getTickets() {
ApiService.getTickets().then(response => {
this.tickets = response.data
this.assignNames(this.tickets)
this.isBusy = false
})
},
// lets wait until the issues are loaded before showing names;
async assignNames() {
let tickets = await this.tickets
var i
for (i = 0; i < this.tickets.length; i++) {
if (tickets[i].assigned_to !== null) {
const result = this.userProfiles.filter(profile => {
return profile.uid == tickets[i].assigned_to
})
tickets[i].assigned_to = result[0].firstname + ' ' + result[0].lastname
}
}
}
}
}
</script>
There are several ways you could do this. Here is the one I prefer without async/await:
created() {
this.load();
},
methods: {
getUserProfiles: function() {
return ApiService.getUserProfiles().then(response => {
this.userProfiles = response.data
})
},
getTickets() {
return ApiService.getTickets().then(response => {
this.tickets = response.data
})
},
load() {
Promise.all([
this.getUserProfiles(),
this.getTickets()
]).then(data => {
this.assignNames();
this.isBusy = false;
});
},
assignNames(){
const tickets = this.tickets;
for (let i = 0; i < this.tickets.length; i++) {
if (tickets[i].assigned_to !== null) {
const result = this.userProfiles.filter(profile => {
return profile.uid == tickets[i].assigned_to
})
tickets[i].assigned_to = result[0].firstname + ' ' + result[0].lastname
}
}
}
}

How to implement Ngx-Datatable server side pagination if pagination is not zero based

I am trying to implement server-side pagination in angular 5 based web app.
Problem is the API requires pagination to start from index 1 whereas the library "ngx-datatable" pagination is 0 based.
Here's my current implementation:
mycomponent.html
<ngx-datatable
#usersTable
class='material text-centered'
[rows]='users'
[columns]="usersColumn"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="'auto'"
[externalPaging]="true"
[offset]="page.offset"
[limit]="page.pageSize"
[count]="page.totalElements"
(page)='fetchList($event)'>
</ngx-datatable>
mycomponent.ts
page: any = {
offset: 0,
pageNumber: 1,
pageSize: 10,
totalElements: '',
sortBy: "id",
sortOrder: "desc"
};
ngOnInit() {
this.usersColumn = [
{
name: 'S.NO',
prop: 'sno'
},
{
name: 'First Name',
prop: 'firstName'
},
{
name: 'Last Name',
prop: 'lastName'
},
{
name: 'Email',
prop: 'email',
width: 200
},
{
name: 'Action',
cellTemplate: this.action
}
];
this.fetchList({ offset: 0 });
}
generateSerialNo(pageNo, size, i) {
const index = i + 1;
return pageNo == 1 ? index : (pageNo - 1) * size + index;
}
fetchList(pageInfo) {
this.page.pageNumber = pageInfo.offset + 1;
const { pageNumber, pageSize, sortBy, sortOrder } = this.page);
this.ListService.fetchList(pageNumber, pageSize, sortBy, sortOrder).subscribe(
success => {
if (success && !success['isError']) {
const responseObj = success['responseObject'];
if (responseObj) {
const List = responseObj.content || [];
const { totalElements } = responseObj;
this.users = List.map((item, i) => {
// set serial no. for user in current iteration
const serialNumber = this.generateSerialNo(this.page.pageNumber, this.page.pageSize, i);
return { sno: serialNumber, ...item };
});
this.page.totalElements = totalElements;
}
} else {
this.toastr.error(success['message'], 'Oops!');
}
},
errorResp => {
const error = errorResp['error'];
this.toastr.error(error['message'], 'Oops!');
}
);
Now Say, there's an action column in the table which consists of buttons to block or unblock user which on click calls a function as follows:
blockUnblockUser(toBlock: boolean) {
this.ListService.blockUnblockUser(toBlock, this.selectedUser.id).subscribe(
success => {
if (success && !success['isError']) {
this.fetchList(this.page);
this.utilService.closeModal();
this.toastr.success(success['message'], 'Success!');
} else {
this.utilService.closeModal();
this.toastr.error(success['message'], 'Oops!');
}
},
errorResp => {
const error = errorResp['error'];
this.utilService.closeModal();
this.toastr.error(error['message'], 'Oops!');
});
}
Here's the problem. On page load, I get my list for page number one and page number one is the active page. Now Click on page number 2, in the request param of API this is what goes:
list?pageNumber=2&pageSize=10&sortBy=id&sortOrder=desc
and in response, I get 3 data for page number 2 with 3 items.
Now if I click on the action button to either block or unblock particular user this is what sent in request params:
list?pageNumber=1&pageSize=10&sortBy=id&sortOrder=desc
and in response, I get data based on the page number 1 with 10 items.
but this time the active page in pagination is still "2"?
Please let me know where I am making mistake and how do I fix this. The backend team cannot make the pagination zero-based index for some reason.