"Property 'then' does not exist on type 'void'." when using spinner.show().then() - angular9

From the docomuntation of ngx-Spinner said in FEAUTERS: "show()/hide() methods return promise",
but in my Project in intellij:
this.spinner.show() returns void.
ane therefore when im trying to do this:
onCheckOut() {
this.spinner.show().then(p => {
this.cartService.CheckoutFromCart(1);
});
}
im getting the : ERROR in src/app/components/checkout/checkout.component.ts:33:25 - error TS2339: Property 'then' does not exist on type 'void'.
33 this.spinner.show().then(p => {
how i make it work?

Maybe the documentation is wrong. When I look at the code, it does not return a promise:
show(name: string = PRIMARY_SPINNER, spinner?: Spinner) {
setTimeout(() => {
const showPromise = new Promise((resolve, _reject) => {
if (spinner && Object.keys(spinner).length) {
spinner['name'] = name;
this.spinnerObservable.next(new NgxSpinner({ ...spinner, show: true }));
resolve(true);
} else {
this.spinnerObservable.next(new NgxSpinner({ name, show: true }));
resolve(true);
}
});
return showPromise;
}, 10);
}
Not sure if this was done on purpose or not, but you could raise an issue on Github.
The only way to achieve your solution would be to use the getSpinner method of the service:
const spinnerName = "my-spinner";
this.spinner.show(spinnerName);
this.spinner.getSpinner(spinnerName)
.pipe(
first(({show}) => !!show)
)
.subscribe(() => {
this.cartService.CheckoutFromCart(1);
}
);

Related

Check if an user exist in my database with Node and MySQL [duplicate]

I need to check if entry with specific ID exists in the database using Sequelize in Node.js
function isIdUnique (id) {
db.Profile.count({ where: { id: id } })
.then(count => {
if (count != 0) {
return false;
}
return true;
});
}
I call this function in an if statement but the result is always undefined
if(isIdUnique(id)){...}
I don't prefer using count to check for record existence. Suppose you have similarity for hundred in million records why to count them all if you want just to get boolean value, true if exists false if not?
findOne will get the job done at the first value when there's matching.
const isIdUnique = id =>
db.Profile.findOne({ where: { id} })
.then(token => token !== null)
.then(isUnique => isUnique);
Update: see the answer which suggests using findOne() below. I personally prefer; this answer though describes an alternative approach.
You are not returning from the isIdUnique function:
function isIdUnique (id) {
return db.Profile.count({ where: { id: id } })
.then(count => {
if (count != 0) {
return false;
}
return true;
});
}
isIdUnique(id).then(isUnique => {
if (isUnique) {
// ...
}
});
You can count and find.
Project
.findAndCountAll({
where: {
title: {
[Op.like]: 'foo%'
}
},
offset: 10,
limit: 2
})
.then(result => {
console.log(result.count);
console.log(result.rows);
});
Doc link, v5 Beta Release
I found the answer by #alecxe to be unreliable in some instances, so I tweaked the logic:
function isIdUnique (id, done) {
db.Profile.count({ where: { id: id } })
.then(count => {
return (count > 0) ? true : false
});
}
As Sequelize is designed around promises anyway, alecxe's answer probably makes most sense, but for the sake of offering an alternative, you can also pass in a callback:
function isIdUnique (id, done) {
db.Profile.count({ where: { id: id } })
.then(count => {
done(count == 0);
});
}
}
isIdUnique(id, function(isUnique) {
if (isUnique) {
// stuff
}
});
Extending #Jalal's answer, if you're very conscious about performance implications while maintaining a simple Sequelize structure and you do not need the row data, I suggest you only request one column from the database. Why waste bandwidth and time asking the database to return all columns when you won't even use them?
const isIdUnique = id =>
db.Profile.findOne({ where: { id }, attributes: ['id'] })
.then(token => token !== null)
.then(isUnique => isUnique);
The attributes field tells Sequelize to only request the id column from the database and not sending the whole row's content.
Again this may seem a bit excessive but at scale and if you have many columns that hold a lot of data, this could make a giant difference in performance.
Try the below solution. I tried it and it works well.
const isIdUnique = async (id, model) => {
return await model.count({ where: { id: id } });
};
const checkExistId = await isIdUnique(idUser, User);
console.log("checkExistId: ", checkExistId);

Cannot read property 'rotationOffset' of undefined

I am using react-vr and trying to use the json object to render image, but I'm getting an error that the browser cannot read property 'rotationOffset' of undefined. Below is my code for reference.
static defaultProps = {
portal: 'webTour.json',
} //assigning the json to a variable.
componentDidMount() {
fetch(asset(this.props.portal).uri)
.then(response => response.json())
.then(responseData => {
this.init(responseData);
})
.done
();
}
init(tourConfig) {
// Initialize the tour based on data file.
this.setState({
data: tourConfig,
locationId: null,
nextLocationId: tourConfig.firstPhotoId,
rotation: tourConfig.firstPhotoRotation + (tourConfig.photos[tourConfig.firstPhotoId].rotationOffset || 0),
});
}
render() {
//some code
const locationId = this.state.locationId;
const photoData = (locationId && this.state.date.photos[locationId]) || null;
const rotation = this.state.data.firstPhotoRotation + ((photoData && photoData.rotationOffset) || 0);
const isLoading = this.state.nextLocationId !== this.state.locationId;
return (
<Pano source = {asset(this.state.data.photos[this.state.nextLocationID].uri)} />
}
And below is my json file for reference.
{
"nave_icon": "gateway.png",
"firstPhotoID" : "112001",
"firstPhotoRotation" : 90,
"photos":{
"112001":{
"rotationOffset": 0,
"uri": "CustomPano_2.jpg",
}
}
}
What I'm trying to do is that change the background image with the objects inside the Pano. Am I missing any essential syntax? I've spent hours to figure out the problem is not working. Any help is much appreciated.

Object from Observable then Array from Observable inside a foreach. how to order it?Asynchronous Angular 4/5

Here is my problem.
I'm running a method that sends me a json (method = myTableService.getAllTables ()), to create an object (object = this.myTables).
Then I execute the method for each, for each element of this.myTables I execute a new request (request = this.myTableService.getTableStatut (element.theId)).
I retrieve data from a new json to create an object (object = myTableModel).
Each result will be added to this.myTableListProvisory.
The problem is the order of execution.
It execute the console.log before the end of the for each...
This.myTableListProvisory.length and this.myTableList.length return 0.
How to wait for the end of the for each run before running the console.log?
Thank you
ngOnInit() {
this.myTableService.getAllTables()
.subscribe(data => {
this.myTables = data;
this.myTableList = this.getAllTableStatut(this.myTables);
console.log("this.myTableList.length : " + this.myTableList.length);
}, err => {
console.log(err);
})
}
getAllTableStatut(myTables: any) {
this.myTableListProvisoire = [];
myTables.forEach(element => {
this.myTableService.getTableStatut(element.theId)
.subscribe(data => {
this.statut = data;
this.myTableModel = new MyTableModel(element.tableNumber, this.statut.name, element.theId);
this.myTableListProvisoire.push(this.myTableModel);
})
console.log("this.myTableListProvisoire.length : " + this.myTableListProvisoire.length);
})
return this.myTableListProvisoire;
}
Result of console.log
this.myTableListProvisoire.length : 0
this.myTableList.length : 0
UPDATE
I have simplified the code ... I put it in its entirety for the understanding. What I need is to sort the array after it is done. The problem is that I don't know how to use a flatMap method in a query inside a foreach ... I have temporarily placed the sort method inside the subscribe which is a bad solution for the performance. That's why I want to do my sort after the creation of the array. Thank you
export class MyTableComponent implements OnInit {
myTables: any;
statut: any;
myTableModel: MyTableModel;
myTableList: Array<MyTableModel>;
myTableListProvisoire: Array<MyTableModel>;
i: number;
j: number;
myTableModelProvisoire: MyTableModel = null;
constructor(public myTableService: MyTableService) { }
ngOnInit() {
this.myTableService.getAllTables()
.subscribe(data => {
this.myTables = data;
this.myTableList = this.getAllTableStatut(this.myTables);
}, err => {
console.log(err);
})
}
getAllTableStatut(myTables: any) {
this.myTableListProvisoire = [];
myTables.forEach(element => {
this.myTableService.getTableStatut(element.theId)
.subscribe(data => {
this.statut = data;
this.myTableModel = new MyTableModel(element.tableNumber, this.statut.name, element.theId);
this.myTableListProvisoire.push(this.myTableModel);
for (this.j = 0; this.j < this.myTableListProvisoire.length; this.j++) {
for (this.i = 0; this.i < this.myTableListProvisoire.length - 1; this.i++) {
if (this.myTableListProvisoire[this.i].getTableNumber() > this.myTableListProvisoire[(this.i + 1)].getTableNumber()) {
this.myTableModelProvisoire = this.myTableListProvisoire[this.i];
this.myTableListProvisoire[this.i] = this.myTableListProvisoire[(this.i + 1)];
this.myTableListProvisoire[(this.i + 1)] = this.myTableModelProvisoire;
}
}
}
}, err => {
console.log(err);
})
}, err => {
console.log(err);
})
return this.myTableListProvisoire;
}
}
Well Observables are asynchronous actions and will be executed after finishing the current execution block. So when the js engine comes to your
this.myTableService.getTableStatut(element.theId)
.subscribe(data => {
this.statut = data;
this.myTableModel = new MyTableModel(element.tableNumber, this.statut.name, element.theId);
this.myTableListProvisoire.push(this.myTableModel);
})
it will only create a subscription, but the code inside of it will be executed after all the other code in the block. So that's why your console.log is being executed before you get any data. So you need to place it inside the .subscribe block to see the. I think there can be a better solution to get the data, but I don't know the structure of the app, so I can't advice. If you create an example on https://stackblitz.com/ I could probably help you out with a better solution.

Delete row data from Firebase

I want to delete one clicked row from Firebase in my smart table. I am using Angular 4.
The smart table code:
<ng2-smart-table [settings]="settings" [source]="bicycleData"
(deleteConfirm)="onDeleteConfirm($event)">
</ng2-smart-table>
My constructor component code:
constructor(
db: AngularFireDatabase, ) {
this.bicyclesList = db.list('bicycle-list')
.snapshotChanges()
.map(changes => {
return changes.map(c => ({
key: c.payload.key,
...c.payload.val()
}))
});
this.bicyclesList.subscribe((data) => {
this.bicycleData = data;
});
}
and component.ts code:
settings = {
delete : {
deleteButtonContent: '<i class="nb-trash"></i>',
confirmDelete: true,
},
}
onDeleteConfirm() function and deleteEnquiry function in service:
onDeleteConfirm(event) {
console.log(event.data);
if (window.confirm('Are you sure you want to delete?')) {
this.deleteEnquiry(event.data);
event.confirm.resolve();
} else {
event.confirm.reject();
}
}
deleteEnquiry(data) {
console.log(data.$key);
this.db.list(`bicycle-list${data.$key}`).remove(data);
}
But it keeps showing me the following error in console:
ERROR TypeError: Cannot read property 'list' of undefined
How can I fix this error ?
Looks like an error in deleteEnquiry.
According to the docs is should be:
deleteEnquiry(data) {
console.log(data.$key);
this.db.list('bicycle-list').remove(data.$key);
}

Update JSON variable based on Mongoose results

I have a JSON variable outside of mongoDB collection as below
var outputJson = [
{
'Product' : 'TV',
'isSelected': 0
},
{
'Product' : 'Radio',
'isSelected': 0
},
{
'Product' : 'Book',
'isSelected': 0
},
{
'Product' : 'Watch',
'isSelected': 0
}
]
Now I want to update the isSelected key if the product exits in MongoDB; I want something like below
var outputJson = [
{
'Product' : 'TV',
'isSelected': 0
},
{
'Product' : 'Radio',
'isSelected': 1
},
{
'Product' : 'Book',
'isSelected': 0
},
{
'Product' : 'Watch',
'isSelected': 1
}
]
Here is the code that I am trying, but I am not getting the above result
outputJson.forEach(function(key,value){
wishlistData.find({userID:req.user.id}, function(err,data{
data.forEach(function(k,i){
if (data[i].product=== outputJson[value].Product){
outputJson[value].isSelected = 1
}
})
});
})
Any help is appreciated
Firstly, the callback function to forEach is called with the item in the array as the first argument, so data[i] and outputJson[value] are redundant.
You should make use of mongoose's findOne method to see if there's at least one match, and you can pass in Product as follows
outputJson.forEach(function(item) {
wishlistData.findOne({userID: req.user.id, product: item.Product}, function(err, data) {
if (data !== null) { // if it actually found a match
item.isSelected = 1;
}
});
});
But keep in mind that mongoDB queries are asynchronous, so outputJson would still be the same right after the forEach loop. You might want to use promises and Promise.all to ensure that you do stuff with outputJson after all the queries have been processed:
Promise.all(outputJson.map(function(item) {
return wishlistData.findOne({userID: req.user.id, product: item.Product}).then(function(err, data) {
if (data !== null) { // if it actually found a match
item.isSelected = 1;
}
});
})).then(function() {
// do stuff with outputJson here
});
Replace this
if (data[i].product=== outputJson[value].Product){
outputJson[value].isSelected = 1
}
by
if (data[k].product=== outputJson[key].Product){
outputJson[key].isSelected = 1
}
each callback function have first argument as index
First thing, why are you doing the same mongo query repeatedly for each object in the Array, as it will give you the same result. Also use the lodash library 'lodash'. This is how you can achieve this:
var _ = require('lodash')
wishlistData.find({userID:req.user.id}, function (err, data) {
var dataMap = _.indexBy(data, "product");
outputJson.forEach(function(key,value){
if(!_.isEmpty(_.get(dataMap, key.Product))) {
key.isSelected = 1;
}
})
}
Thank you #Ambyjkl, you guidence worked Promise made the trick, I made minor changes to your script and it started working
Promise.all(outputJson.map(function(i,k) {
return wishlistData.findOne({userID: req.user.id, product: i.Product}).then(function(data, err) {
if (data !== null) { // if it actually found a match
i.isSelected = 1;
}
});
})).then(function() {
console.log(outputJson);
});