Vue.js - function not executed when data are updated - javascript

I have this function code in my vue component methods that will remove the customers data if a button is clicked and show a chrome notification.
deleteCustomer(id) {
console.log('deleting customer:' + id);
db.customers.delete(id).then( () => {
console.log('customer '+ id +' deleted!');
browser.notifications.create('deleted',{
type: 'basic',
iconUrl: 'icons/128.png',
title: 'Data removal',
message: 'data removed with success!'
});
this.viewCustomers();
});
},
At the end of the function I'm calling another method that is supposed to call a dexie.js instance to show in a table all the customers data that are stored. When the component is mounted, all work fine with the viewCustomers function and the table is populated correctly. What I need to fix is that the method is not called after data deletion and the table isn't updating. How I can fix this, is there a vue function I can use or any code modification that can solve this problem?

As mentioned in the docs, Delete items is actually an async call which means it calls the this.viewCustomers() before the item is even deleted, thus it seems that it is not working. The easiest way to resolve this is to use async/await like:
async deleteCustomer(id) {
console.log('deleting customer:' + id);
await db.customers.delete(id);
console.log('customer ' + id + ' deleted!');
browser.notifications.create('deleted', {...});
this.viewCustomers();
},
Now, the this.viewCustomers the function will be only called once the db.customers.delete() function is completed and that should result in the desired output.

After some headche I've found a tricky solution that will give me the ability to update the table with the updated data. I've used the onClicked method of chrome.notifications API and now all works fine, but I'm opened to every suggestion about this problem.
Here is the code I've added in the mounted section of vue instance:
mounted() {
console.log('mounted')
this.$set(this, 'isActive', true)
this.viewCustomers()
browser.notifications.onClosed.addListener( (notificationId) => {
console.log(notificationId)
this.customersList = [];
this.viewCustomers();
})
}

Related

I want to pass user View time of a video to server using an api call on visibilityChange event in react

I want to pass the watch time of a video the user has seen when user closes the page,reload the page or navigate to another page. I am using visibilityChange event for this. When i try to navigate to another page, the api call runs perfectly. But the data i am sending to the api is not updated correctly. I am going to provide the code and the output below so you can understand perfectly what my problem is.
useEffect(async () => {
const x = 0;
console.log("use effect is run number ::::", x + 1);
window.addEventListener("visibilitychange", sendViewTime);
return () => {
window.removeEventListener("visibilitychange", sendViewTime);
};
}, []);
I have added the event listener in the useEffect.
the sendViewTime method is the method i want to call on visibility change event. This Method is working perfectly but for some reason the params are not updated even though i have set their states in their relavant hooks.
const sendViewTime = async () => {
if (document.visibilityState === "hidden") {
console.log("the document is hidden");
const value = localStorage.getItem("jwt");
const initialValue = JSON.parse(value);
console.log("the send View Time is :::", played_time);
const params = {
video_id: video_id_url,
viewTime: played_time,
MET: MET_value,
weight: "",
};
console.log("params are :::", params);
await setEffort(params, initialValue).then((res) => {
console.log("set effort api response is ::: ", res);
});
} else {
console.log("the document is back online");
}
};
//This onProgress prop is from react Player. Here i am updating the state of video progress.
onProgress={(time) => {
console.log("the time is :::", time);
const time_1 = Math.round(time.playedSeconds);
const time_2 = JSON.stringify(time_1);
setPlayed_time(time_2);
console.log("the played time is :::", played_time);
}}
//OUTPUT
// the document is hidden.
// the send View Time is :::
//params are ::: {video_id: '23', viewTime: '', MET: undefined, weight: ''}
//set effort api response is ::: {status: 200, message: 'Success', data: {…}, time: '2.743 s'}
//the document is back online
Never mind guys. I found the solution. It seems that i have to pass played_time and met value as a prop to the useEffect.If you want to know how useEffect works please visit this link. In general is it better to use one or many useEffect hooks in a single component?.

Cloud Firestore query works sometimes but not always

This has me really stumped. I have a method that searches for items in a Firestore database. It works when I call the method directly from a one-off test. It does not work when I call the method from another part of my app with the exact same input.
Here is the method that does the searching:
getProductsStartingWithCategory(textSoFar: string): Observable<Product[]> {
console.log('searching for ', textSoFar);
let endAt = textSoFar + '\uf8ff';
let filteredCollection: AngularFirestoreCollection<Product> =
this.afs.collection('products', ref =>
ref.orderBy('materialType').limit(30).startAt(textSoFar).endAt(endAt)
);
return filteredCollection.snapshotChanges().map(changes => {
return changes.map(a => {
console.log('matched one', a);
const data = a.payload.doc.data() as Product;
data.id = a.payload.doc.id;
return data;
});
});
}
And when I call the method directly from the first page in the app with a test button, it works. That method is as follows:
testTheThing() {
let text: string = 'Car';
this.productService.getProductsStartingWithCategory(text)
.subscribe(data => {
console.log('success', data);
});
}
Again, when I call this method I get results as expected (matching products in the database with materialType 'Carpet'.) Success!
But then, when I use the method from another page in the app, it returns no results. That page is a bit more complicated - essentially the method is being called when user input changes. Here are the relevant parts of the method:
productCategoryChanged(productPurchase: ProductPurchase) {
if (productPurchase.materialType) {
console.log('searching for products starting with "' + productPurchase.materialType + '"');
let unsubscribe = this.productService.getProductsStartingWithCategory(productPurchase.materialType).subscribe(products => {
products.forEach(product => {
// logic goes here...
});
});
// rest of method omitted
In both scenarios, I see the "searching for Car" in the console.log message. The search text is identical. I've tried numerous times with numerous different search text (all of which are in the database). The logging shows the method is being called with the right input, but for some reason I only find results when calling it from the "test" method. Why is that?
I've tried trimming the input. I do have another collection of 'products' hooked up to an observable, but I don't think that matters. I also have used this exact strategy for a "customer" search and that works fine. This "products" search is almost identical but it doesn't work.

Firebase update() not a function with a query

I'm trying to update a property in a record in Firebase Database, with AngularJS. I can set up a query to find my record:
firebase.database().ref('en/').orderByChild('word').equalTo('the').once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val())
});
})
I can update my property, if I hardcode in the record's key:
firebase.database().ref('en/-KloeQHDC-mugPjJMAG4').update({ wordFrequency: 111 })
But if I set up a query to find the record and then update it, I get an error message update is not a function:
firebase.database().ref('en/').orderByChild('word').equalTo('the').update({ wordFrequency: 9001 })
Another answer suggests calling update() from inside a forEach loop:
firebase.database().ref('en/').orderByChild('word').equalTo('the').once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val()); // this works
childSnapshot.ref().update({ wordFrequency: 9001 });
});
});
That returns an error message TypeError: childSnapshot.ref is not a function. I don't see how childSnapshot is a Firebase ref.
Another answer says
When you call update() on a location, Firebase loops over the data
that you pass in (in your case asJson) and for each key performs a
ref.child(key).set(value).
If update() loops over the data, why should I call update() from inside a forEach loop? The documentation doesn't show calling update() from inside a forEach loop.
The Firebase Database SDK provides a Reference.update() method to update data in a single location in a database. Key here is that a Reference is a single location in the database, so it is clear what to update.
My pseudo-code explanation about how multi-path updates work applies to how the database server implements it: given a single location/DatabaseReference it updates each path in the update() call based on that.
A Query can match multiple locations in the database, so it doesn't have an update() method (or set() or remove() for that matter).
To update each location matched by a query, you execute the query and then call update() on each result - either by a child_added listener, or with a value listener and a loop like in your last snippet.
After I posted this question I walked the dog, ate dinner, and then the solution came to me. My new rule is, "The key to Firebase queries is to keep track of the key."
This template is for users to update records in the database. They enter a search term in a form field and click the "Search" button. The $scope.search handler queries the Firebase database and then populates the form fields with the record's properties:
$scope.search = function() {
myFirebase_ref.orderByChild('word').equalTo($scope.word).once('value')
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
$scope.wordKey = childSnapshot.key;
$scope.audioArray = childSnapshot.val().audio;
$scope.ipaArray = childSnapshot.val().ipa;
$scope.language = childSnapshot.val().language;
$scope.longLanguage = childSnapshot.val().longLanguage;
$scope.phonemeArray = childSnapshot.val().phonemes;
$scope.translationArray = childSnapshot.val().translations;
$scope.word = childSnapshot.val().word;
$scope.wordFrequency = childSnapshot.val().wordFrequency;
$scope.$apply();
});
})
.catch(function(error) {
console.error("Authentication failed:", error.message);
});
};
Note at the top of the property assignments I have $scope.wordKey = childSnapshot.key;. I'm keeping track of the record's key.
The user then updates a field. Each field has a button next to it for "Update". Each button goes to a handler. For example, to update the wordFrequency field I have this handler:
$scope.updateFrequencyRank = function() {
firebase.database().ref('en/' + $scope.wordKey).update({ wordFrequency: $scope.wordFrequency })
};
One line of code and it works! Even better, I made an onComplete function to tell me if the update succeeded:
$scope.updateFrequencyRank = function() {
var onComplete = function(error) {
if (error) {
console.log('Update failed');
} else {
console.log('Update succeeded');
}
};
firebase.database().ref('en/' + $scope.wordKey).update({ wordFrequency: $scope.wordFrequency }, onComplete);
};

Resource object returned instead of Mongoose.count value

I'm having a little trouble trying to retrieve Mongoose.count values from a function in my back end API within my mean.js application. Everything is routed correctly as far as I can see, and seems to be working absolutely fine until I get to the front end angular code and try to retrieve the data from the API via a service and $resource.
Here's my back end API function to retrieve the count of listings in a particular category, where the category is passed in correctly as parameter.
exports.getListingCountForSpecificCategory = function(req, res, next, category) {
Listing.count({
category: category,
quantityAvailable: { $gt: 0 },
listingActive: true
}, function(err, count){
if(err) {
console.log(err);
} else {
console.log(category + ': ' + count);
res.jsonp(count);
}
});
};
This runs correctly and within the console.log()
console.log(category + ': ' + count);
The category count is returned correctly. So, everything working correctly!
Until I get to retrieving the count value with angular on the front end. Here's the function I've written:
$scope.listingsCount = function(category) {
$scope.catCount = Listings.listingsCategoryCount.query({
category: category.alias
});
$scope.catCount.$promise.then(function(count){
category.listingCount = count;
});
};
When this function is run and the category object is passed into it, instead of it retrieving the count value e.g. 14, it seems to retrieve a resource promise object instead, with the count value nowhere to be seen. I've looked over the code a few times and can't for the life of me figure out why.
Here's the service I'm using, just in case you need to see it.
listingsCategoryCount: $resource('listingscount/:category', {
category: '#_category'
}, {
query: {
method: 'GET',
isArray: false
}
}),
It's a mystery to me why the count value isn't being returned. I may be going about this incorrectly of course. Any help would be greatly appreciated.
Thanks
https://docs.angularjs.org/api/ngResource/service/$resource:
On success, the promise is resolved with the same resource instance or collection object, updated with data from server.
Change this: res.jsonp(count); to res.jsonp({ count: count }); and it should work: you'll get a Resource object with property count.

Asyncronus function return

I'm working at an application in Titanium Studio. I have an MVC infrastructure implemented, and in a controller I want to get some data from the Cloud and only after that to call the view. The code is similar to this.
Default : function() {
Cloud.Objects.query({
classname : 'Customer',
}, function(e) {
if (e.success) {
Ti.API.info('aci ' + e.Customer);
favorites = e.Customer;
return this.view("Default", favorites);
} else {
alert('Error:\\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
},
}
The thing is, that the first function has to return "this.view("Default", favorites);", not the callback from the query. Also, the query function is asyncronus and I have to wait for the data, and only then call the view.
Do you have any ideas?
Thank you
Create an even handler for some custom event like receiveCustomer.
When customer retrieved, fire the event receiveCustomer and set customer as event data or initialize some variable outside the callback with retrieved data (but in this case before event triggering). In event hander onReceiveCustomer get the customer from the event data or from that variable and render the view.

Categories