AngularFire2 iterate through array of objects and get data from realtime database - javascript

I have to go through an array of items and fetch the prices in the realtime database, but I want to show a loading message on start and after I finish loading I want to remove the loading message, but the way I did the message does not work its removed before the end of loading:
let loading = this.loadingCtrl.create({
content: 'Waiting...'
});
loading.present();
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
});
}
loading.dismiss();
How can I do this correctly?

You need to hide the loading indicator inside the subscriber. The simplest way is to hide it when the first data comes in:
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
loading.dismiss();
});
}
A bit more tricky is to hide it after all data comes back, but it doesn't have to be too hard. A simple way is to count how many responses you've gotten back. Once that is the same as the number of items in the cart, you can hide the loading indicator.
var responseCount = 0;
for (let i = 0; i <= this.Cart.length - 1; i++) {
let product = this.db.object('/menuItems/' + this.Cart[i].item.itemId);
product.valueChanges().subscribe((prodData: any) => {
if (prodData != null) {
this.Cart[i].item.price = prodData.price[0];
}
if (responseCount++ == this.Cart.length) loading.dismiss();
});
}

Related

Cypress - Create a new 'it' on each loop cycle

I'm automating the completion of a questionnaire via Cypress using fixtures. I need to create a new IT statement on each iteration of a loop running as currently if 1 set fails in the loop, then the rest of the dataset does not run.
Any help would be appreciated.
context('Questionnaire Completion', () => {
Cypress.Cookies.debug(true);
beforeEach(function() {
cy.fixture('data_set_4').then((testdata) => {
this.data = testdata
});
});
describe ('I will complete the form with each entry in the data set', function() {
it ('I will complete the form with each entry in the data set', function() {
for (let i = 0; i < this.data.testdata.length ; i++) {
participantcreation(this.data.testdata[i].DataEntry);
//I will enter a name and click Next
Name(this.data.testdata[i].DataEntry);
for (let j = 1; j < 31 ; j++) {
let answer = this.data.testdata[i]['Q' + j] - 1;
cy.get('#questionnaire_question_'+j+'_'+answer).click({ force: true });
}
});
});
});
Not entirely sure about what is being asked here but if you wish to create multiple 'its' depending on what you need you can just put it in a loop
describe('Tests', () => {
var i;
for (i = 0; i < 5; i++) {
it(`Test ${i}`, () => {
cy.wait(200)
});
}
});

Matching strings don't trigger condition in Javascript

I am trying to do a very simple stock counting app, and display dynamically the stocks for each item. When I try to pair the button with its item, it doesn't work, even though the 2 strings are actually a match.
Here is the faulty function:
socket.on('Stock init', (data) => {
items = data.items;
displayStock(items);
});
function displayStock(items) {
fridgeItem.forEach((fridgeItem) => {
for (let i = 0; i < items.length; i++) {
var databaseProduct = items[i].name;
var databaseQuantity = items[i].chilled.toString();
console.log(fridgeItem.textContent, databaseProduct);
}
if (fridgeItem.textContent === databaseProduct) {
fridgeItem.textContent = databaseProduct + ' ' + databaseQuantity;
} else {
console.log('err');
}
});
}
Answer might be stupid but I can't see it at the moment. Thanks

amazon-chime-sdk-js display self video

I created a video application using chime js SDK with the help of the documentation https://aws.github.io/amazon-chime-sdk-js/index.html
const indexMap = {};
const acquireVideoElement = tileId => {
for (let i = 0; i < 16; i += 1) {
if (indexMap[i] === tileId) {
return videoElements[i];
}
}
for (let i = 0; i < 16; i += 1) {
if (!indexMap.hasOwnProperty(i)) {
indexMap[i] = tileId;
return videoElements[i];
}
}
throw new Error('no video element is available');
};
const releaseVideoElement = tileId => {
for (let i = 0; i < 16; i += 1) {
if (indexMap[i] === tileId) {
delete indexMap[i];
return;
}
}
};
const observer = {
videoTileDidUpdate: tileState => {
if (!tileState.boundAttendeeId || tileState.localTile || tileState.isContent) {
return;
}
meetingSession.audioVideo.bindVideoElement(tileState.tileId, acquireVideoElement(tileState.tileId));
},
videoTileWasRemoved: tileId => {
releaseVideoElement(tileId);
}
};
meetingSession.audioVideo.addObserver(observer);
const audioMix = document.getElementById('meeting-audio');
meetingSession.audioVideo.bindAudioElement(audioMix);
meetingSession.audioVideo.start();
meetingSession.audioVideo.startLocalVideoTile();
This is working good and I can see all the attendees who is joined in the meeting. But I need to show my video also in a tag. Is it possible?
In your videoTileDidUpdate, for your video tile to show, where are you binding the local tile, I see that if tileState.localTile is true you are returning and the bindVideoElement is not getting called hence your localTile is not showing up. Can you please remove the localTile check and see if that works as the initial step.
videoTileDidUpdate: tileState => {
// Ignore a tile without attendee ID, a local tile (your video), and a content share.
const { allUsers } = this.props;
if (!tileState.boundAttendeeId || tileState.isContent) {
return;
}
if( tileState.localTile ) {
if( Obj[tileState.boundExternalUserId]['tileId'] === tileState.tileId) {
return;
}
}
this.meetingSession.current.audioVideo.bindVideoElement( tileState.tileId,document.getElementById(tileState.boundExternalUserId) );
}

Display backend data in reactJS

i am trying to display backend data in the front with react, i did recieve the data because when i inspect the response in the Network tab in the console i found them,
now to display this data on the interface i am calling the loadData() function in componentDidMount :
componentDidMount() {
this.loadTime();
this.loadOtherData();
}
but in these two function i am using a setTimeOut() so i can display if i don't do a setTimeOut i'm getting null on the render
loadTime() {
const dateList = [];
$('.day').each((index, d) => {
dateList.push(new Date(d.innerText));
});
const displayImputation = {
idMantis: $('#mantis').html(),
dateList: dateList,
userId: 1
};
this.props.store.loadImputation(displayImputation);
setTimeout(() => {
const response = this.props.store.privateImputationData;
for (let i = 0; i < response.length; i += 1) {
const stampToDate = response[i].cra.date;
const o = moment(stampToDate).day();
for (let x = 0; x < $('.App input').length; x += 1) {
if (x === o) {
const input = $('.App input')[x - 1];
input.value = response[i].temps;
}
}
}
}, 500); }
is it a good practice or is there another solution ?

How to find out when files traverse is over?

I want to create my own drag and drop component and i use this:
Does HTML5 allow drag-drop upload of folders or a folder tree?
everything works fine, but i want to find out when files traverse is over, because i want to create an array of string, which contains file names and then do sth.
traverseFileTree function contains callbacks so there are async tasks. I need to wait until callbacks are done and i don't know how to do it. I would use jQuery.Deffered but traverseFileTree is called from a loop and -in addition- this is a recursive function.
this.dndElement.addEventListener('drop', (ev: any) => {
var items = ev.dataTransfer.items;
for (var i = 0; i < items.length; i++) {
this.traverseFileTree(items[i].webkitGetAsEntry());
}
// i want to wait until callbacks in the traverseFileTree are done and do sth with fileNames array
});
public traverseFileTree(item, path?) {
path = path || "";
if (item.isFile) {
item.file((file) => {
this.fileNames.push(file.name);
});
} else if (item.isDirectory) {
var dirReader = item.createReader();
dirReader.readEntries((entries) => {
for (var j = 0; j < entries.length; ++j) {
this.traverseFileTree(entries[j], path + item.name + "/");
}
});
}
}
UPDATE:
I did sth like this:
this.dndElement.addEventListener('drop', (ev: any) => {
var items = ev.dataTransfer.items;
for (var i = 0; i < items.length; i++) {
var item = items[i].webkitGetAsEntry();
if (item) {
this.traverseFileTree(item);
}
}
Promise.all(this.promises).then(() => { console.log(this.fileNames); });
});
public traverseFileTree(item, path?) {
path = path || "";
console.log(item);
if (item.isFile) {
this.fileNames.push(item.fullPath);
} else if (item.isDirectory) {
this.promises.push(new Promise((resolve, rejected) => {
var dirReader = item.createReader();
dirReader.readEntries((entries) => {
for (var j = 0; j < entries.length; ++j) {
this.traverseFileTree(entries[j], path + item.name + "/");
}
resolve();
})
}));
}
}
and now i get list of files ... but only from "first level".
Adir
Bdir
1File
2File
Cdir
3File
4File
5File
6File
And i get 1File,2File,5File,6File but 3File,4File don't. Why?
You kick off here :
this.traverseFileTree(items[i].webkitGetAsEntry());
And then the function public traverseFileTree(item, path?) { takes over. The function is sync (even though its recursive). Once it returns you should already be in good shape 🌹
However please note that this is webkit only :https://developer.mozilla.org/en/docs/Web/API/DirectoryReader#readEntries and is likely to be removed at some point.

Categories

Resources