Transform object to object where "equal" property exists to the value of "equal" - lodash

I have a deep object like cats below, and I'm looking for a simple way to remove all properties deeply where the nested property is set to equal.
const cats = {
love: {
meow: {
equal: 2,
},
dolphin: {
hi: 'meow',
},
doggo: true,
soup: undefined,
vampire: {},
deep: {
ocean: {
love: {
equal: 'hi',
},
},
},
},
};
To this:
const cats = {
love: {
meow: 2,
deep: {
ocean: {
love: 'hi',
},
},
},
};

You can use a recursive _.transform():
const cats = {
love: {
meow: {
equal: 2,
},
dolphin: {
hi: 'meow',
},
doggo: true,
soup: undefined,
vampire: {},
deep: {
ocean: {
love: {
equal: 'hi',
},
},
},
},
};
const fn = (collection) => _.transform(collection, (r, v, k) => {
if(_.isArray(v)) r[k] = fn(v);
else if (_.isObject(v)) {
if(_.has(v, 'equal')) r[k] = _.get(v, 'equal');
else {
const value = fn(v);
if(!_.isEmpty(value)) r[k] = value;
}
} else if(!_.isUndefined(v)) r[k] = v;
});
const result = fn(cats);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Using #OriDori's answer I customized it to not set empty / unwanted props.
const fn = collection => lodash.transform(collection, (r, v, k) => {
if (lodash.isPlainObject(v)) {
if (lodash.has(v, 'equal')) {
r[k] = lodash.get(v, 'equal');
} else {
const d = fn(v);
if (lodash.size(d)) {
r[k] = d;
}
}
}
});

Related

sequelize findandcountall function return same data when using pagination

I am using sequelize: 6.9.0, sequelize-cli: ^6.3.0, express: 4.17.1, pg: 8.7.1
i have a problem when using sequelize findAndCountAll, when i using include other models it will return same data when i'm using paging.
Here is my code for House Table
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo, project, isNew } =
req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = {};
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (project) {
filter.projectId = project;
}
if (isNew) {
filter.isNew = isNew;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.price = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.price = { [Op.gte]: firstPrice };
} else {
filter.price = { [Op.between]: [firstPrice, secondPrice] };
}
}
const HousesData = await Houses.findAndCountAll({
limit,
offset,
where: filter,
attributes: [
"id",
"name",
"description",
"location",
"price",
"tanah",
"bangunan",
"lantai",
"kamar_tidur",
"kamar_mandi",
"isNew",
],
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
});
if (HousesData) {
const response = getPagingData(HousesData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
}
my paging function
const getPagination = (page, size) => {
const newPage = page ? page - 1 : 0;
const limit = size ? +size : 10;
const offset = newPage != 0 ? newPage * limit : 0;
return { limit, offset };
};
const getPagingData = (data, page, limit) => {
const { count: totalItems, rows: dataRows } = data;
const currentPage = page ? +page : 1;
const totalPages = Math.ceil(totalItems / limit);
return { totalItems, totalPages, currentPage, dataRows };
};
module.exports = { getPagination, getPagingData };
Let's say i have 10 data
a,b,c,d,e,f,g,h,i,j
if i see first page
http://localhost:3006/api/v1/house?size=5&page=1
it will return a,b,c,d,e (this is right)
and if i see next page
http://localhost:3006/api/v1/house?size=5&page=2
it will return e,d,c,b,a (only reverse not showing f,g,h,i,j)
and if i see all the data it will return correct data
http://localhost:3006/api/v1/house?size=10&page=1
it will return j,i,h,g,f,e,d,c,b,a
but if i disabled
include: [
{ model: Developers, attributes: ["id", "name"] },
{ model: Cities, attributes: ["id", "name"] },
{ model: Projects, attributes: ["id", "name"] },
],
it return the right data when use paging.
my model for House is here
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Houses", {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.STRING(22),
},
name: {
type: Sequelize.STRING,
},
projectId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Projects",
key: "id",
},
},
cityId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Cities",
key: "id",
},
},
developerId: {
type: Sequelize.STRING(22),
onDelete: "CASCADE",
references: {
model: "Developers",
key: "id",
},
},
description: {
type: Sequelize.TEXT,
},
location: {
type: Sequelize.STRING,
},
price: {
type: Sequelize.BIGINT,
},
tanah: {
type: Sequelize.INTEGER,
},
bangunan: {
type: Sequelize.INTEGER,
},
lantai: {
type: Sequelize.INTEGER,
},
kamar_tidur: {
type: Sequelize.INTEGER,
},
kamar_mandi: {
type: Sequelize.INTEGER,
},
house_thumbnail: {
type: Sequelize.STRING,
},
isNew: {
type: Sequelize.BOOLEAN,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Houses");
},
};
i also use same paging method on other table. but other table works fine, only this table that got messed up.
the other table named Project function is here for reference
index: async (req, res) => {
const { page, size, developer, city, priceone, pricetwo } = req.query;
const { limit, offset } = getPagination(page, size);
try {
let filter = { haveDeveloper: true };
if (developer) {
filter.developerId = developer;
}
if (city) {
filter.cityId = city;
}
if (priceone && pricetwo) {
const firstPrice = parseInt(priceone);
const secondPrice = parseInt(pricetwo);
if (firstPrice === 100000000 && secondPrice === 100000000) {
filter.minPrice = { [Op.lte]: firstPrice };
} else if (firstPrice === 2000000000 && secondPrice === 2000000000) {
filter.minPrice = { [Op.gte]: firstPrice };
} else {
filter.minPrice = { [Op.between]: [firstPrice, secondPrice] };
}
}
const projectsData = await Projects.findAndCountAll({
limit,
offset,
where: filter,
attributes: ["id", "name", "image", "location",'minPrice'],
include: [
{ model: Cities, attributes: ["id", "name"] },
{ model: Developers, attributes: ["id", "name"] },
{ model: ProjectFacilities, attributes: ["facility"] },
],
});
if (projectsData) {
const response = getPagingData(projectsData, page, limit);
res.status(200).json({
status: "success",
message: "Data Available",
data: response,
});
} else {
res.status(200).json({
status: "success",
message: "There is No Data",
data: "No Data",
});
}
} catch (error) {
console.log(error);
return next(
new HttpError(
"Something went wrong, could not get project.",
500,
error
)
);
}
},
the Project model
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Projects extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Projects.belongsTo(models.Developers, { foreignKey: 'developerId' })
Projects.belongsTo(models.Cities, { foreignKey: 'cityId' })
Projects.hasMany(models.ProjectFacilities, { foreignKey: 'projectId' })
Projects.hasMany(models.Houses, { foreignKey: 'projectId' })
}
};
Projects.init({
name: DataTypes.STRING,
image: DataTypes.STRING,
description: DataTypes.TEXT,
location: DataTypes.STRING,
minPrice:DataTypes.BIGINT,
haveDeveloper: DataTypes.BOOLEAN,
cityId: DataTypes.STRING,
developerId: DataTypes.INTEGER
}, {
sequelize,
modelName: 'Projects',
});
return Projects;
};
sql generated by sequelize for House page 1 with 5 data
SELECT "Houses"."id", "Houses"."name", "Houses"."description", "Houses"."location", "Houses"."price", "Houses"."tanah", "Houses"."bangunan", "Houses"."lantai", "Houses"."kamar_tidur", "Houses"."kamar_mandi", "Houses"."isNew", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "City"."id" AS "City.id", "City"."name" AS "City.name", "Project"."id" AS "Project.id", "Project"."name" AS "Project.name" FROM "Houses" AS "Houses" LEFT OUTER JOIN "Developers" AS "Developer" ON "Houses"."developerId" = "Developer"."id" LEFT OUTER JOIN "Cities" AS "City" ON "Houses"."cityId" = "City"."id" LEFT OUTER JOIN "Projects" AS "Project" ON "Houses"."projectId" = "Project"."id" LIMIT 5 OFFSET 0;
sql generated by sequelize for Project page 1 with 5 data
SELECT "Projects".*, "City"."id" AS "City.id", "City"."name" AS "City.name", "Developer"."id" AS "Developer.id", "Developer"."name" AS "Developer.name", "ProjectFacilities"."id" AS "ProjectFacilities.id", "ProjectFacilities"."facility" AS "ProjectFacilities.facility" FROM (SELECT "Projects"."id", "Projects"."name", "Projects"."image", "Projects"."location", "Projects"."minPrice", "Projects"."cityId", "Projects"."developerId" FROM "Projects" AS "Projects" WHERE "Projects"."haveDeveloper" = true LIMIT 5 OFFSET 0) AS "Projects" LEFT OUTER JOIN "Cities" AS "City" ON "Projects"."cityId" = "City"."id" LEFT OUTER JOIN "Developers" AS "Developer" ON "Projects"."developerId" = "Developer"."id" LEFT OUTER JOIN "ProjectFacilities" AS "ProjectFacilities" ON "Projects"."id" = "ProjectFacilities"."projectId";
is there any solution for this? thank you very much for your all help and attention!
Please try thi
const getPagination = (page = 1, size = 10) => {
const offset = (page - 1) * size ;
const limit = size ;
return { limit, offset };
};

Ant Design Vue | Upload in Form | How to set initialValue

I'm having problems defining the initialValue in an Upload component, other thing I tried was using a watcher and updating the formValue and the method that update the props FileList. ¿Someone has any idea how this work?
Parent.vue
<Child :file="file"/>
...
async loadFile(item) {
this.loading = true
const { data } = await axios(..., {
...
responseType: 'blob',
})
const file = new File([data], item.name, { type: data.type });
this.file= {
Id: item.id,
Type: item.attributes.type,
IsPublic: item.attributes.is_public,
Descr: item.attributes.descr,
File: [file]
}
this.showForm();
this.loading = false
},
Children.vue
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!formats"
:remove="removeFileEvt"
v-decorator="[
'File',
{
valuePropName: 'fileList',
getValueFromEvent: getValueEvt,
rules: [{ required: true, message: 'Select a file' }]
},
]" >
<a-button> <a-icon type="upload" /> Select a file</a-button>
</a-upload>
methods: {
beforeUploadEvt(file) {
this.form.setFieldsValue({
File: [file]
});
return false;
},
removeFileEvt() {
this.formulario.setFieldsValue({
Archivo: []
});
},
getValueEvt(e) {
if (Array.isArray(e)) {
return e;
}
if(e && e.fileList.length > 1) {
return e && [e.fileList[1]];
}
return e && e.fileList;
},
},
watch: {
adjunto: {
immediate: true,
deep: true,
handler(obj) {
if(obj.File) {
this.getValueEvt(obj.File);
// this.formulario.setFieldsValue({
// File: obj.File
// });
}
}
}
}
Trying the most basic example I could think, using the property defaultFileList
<a-upload
:accept="formats"
:before-upload="beforeUploadEvt"
:disabled="!format"
:remove="removeFileEvt"
:default-file-list="this.file.File">
<a-button> <a-icon type="upload" /> Select file</a-button>
</a-upload>
And then, this is the console warnings and errors I got, so seems to be something about type.
If anyone still seeking for an answer for this. You don't need to load file, wrapping your data in appropriate object helps. As in this example
fileList: [{
uid: '-1',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}]
<a-upload
....
:file-list="fileList"
>

I'm getting the error in vue.js - Unexpected side effect in "filteredTeamsData" computed property

Unexpected side effect in "filteredTeamsData" computed property
I have imported the two JSON file
import seasonList from '../assets/data/season_list.json'
import team data from '../assets/data/match_team.json'
Code -
export default {
name: 'SeasonSplit',
components: {
TableElement,
},
data () {
return {
selected: '1',
teamData: teamData,
teamList: [],
seasonList: seasonList,
filteredData: [],
tableColumns: ['toss_wins', 'matches', 'wins', 'losses', 'pts']
}
},
computed: {
filteredTeamsData: function () {
this.dataArr = []
this.filteredData = []
this.teamList = []
teamData.forEach(element => {
if(element.season == seasonList[this.selected-1]){
this.filteredData.push(element)
this.teamList.push(element.team)
this.dataArr.push(element.wins)
}
})
// console.log(this.filteredData)
return this.dataArr
}
}
}
I'd do it as follows:
export default {
name: 'SeasonSplit',
components: {
TableElement,
},
data () {
let filteredData = [];
let teamList = [];
let dataArr = [];
teamData.forEach(element => {
if(element.season == seasonList[this.selected-1]){
filteredData.push(element)
teamList.push(element.team)
dataArr.push(element.wins)
}
});
return {
selected: '1',
teamData: teamData,
teamList: teamList ,
seasonList: seasonList,
filteredData: filteredData ,
tableColumns: ['toss_wins', 'matches', 'wins', 'losses', 'pts'],
filteredTeamsData: dataArr
}
}

Try to call the vuex getter in watch

I'm trying to call a Vuex getter in the component watch.
But it tells me that it is undefined what is not.
So i try to return the getter in the computed object but still doesn t work.
name: "FreeTalk",
computed: {
...mapGetters(['getCharacter','getResultStatus', 'getFreeTalkText', 'getResult', 'freeTalkResult', 'getFreeTalkNoNative', 'getFreeTalkMedium','getFreeTalkNative']),
progressStatus() {
return this.getResult.progress
},
getStatus() {
return this.getResultStatus
}
},
watch: {
progressStatus: (val) => {
if (val == 100) {
this.status = this.getStatus()
if (this.getStatus === 0) {
this.outputText = this.getFreeTalkNoNative.result;
} else if (this.getStatus === 1) {
this.outputText = this.getFreeTalkMedium;
} else if (this.getStatus === 2) {
this.outputText = this.getFreeTalkNative;
}
}
}
},
data() {
return {
outputText: '',
ready: false,
isRecordDone: false,
status: -1
}
}
}

How to combine multiple filters in Vue.js

I would like to combine some filters in my Vue app:
app = new Vue({
el: '#app',
data: {
products: null,
productGroups: null,
productPackageWeights: null,
checkedProductGroupItems: [],
checkedProductPackageWeights: [],
},
created: function created() {
this.fetchData();
},
computed: {
productsFilter: function () {
return this.filterProductGroupItems;
}
},
methods: {
fetchData: function () {
var vm = this
axios.get([MY_JSON_FILE])
.then(function(response){
console.log(response.data.filter_data.product_package_weights);
vm.productPackageWeights = response.data.filter_data.product_package_weights;
vm.productGroups = response.data.filter_data.product_groups;
vm.products = response.data.products;
}).catch(function (error) {
alert('Het ophalen van de producten is niet gelukt');
});
},
filterProductGroupItems: function(data) {
if (this.checkedProductGroupItems.length == 0) return true;
return this.checkedProductGroupItems.includes(data.features.product_groups.value);
},
filterProductPackageWeights: function(data) {
if (this.checkedProductPackageWeights.length == 0) return true;
return this.checkedProductPackageWeights.includes(data.features.product_package_weights);
},
}
});
The code works only for the filterProductGroupItems. How can I combine the filterProductGroupItems and filterProductPackageWeights results in the computed productsFilter function? I'm also planning to make some more filter functions.
Please help
Thanks!
you can do this
computed: {
productsFilter: function () {
return [...this.filterProductGroupItems(), ...this.filterProductPackageWeights()];
}
},
or concat
computed: {
productsFilter: function () {
return this.filterProductGroupItems().concat(this.filterProductPackageWeights());
}
},
the problem may be that you could end up with an array that has [true, Obj, Obj ...] if one filter returns true, so you may want to change the filter to return an empty array
filterProductGroupItems: function(data) {
if (this.checkedProductGroupItems.length == 0) return [];
return this.checkedProductGroupItems.includes(data.features.product_groups.value);
},
filterProductPackageWeights: function(data) {
if (this.checkedProductPackageWeights.length == 0) return [];
return this.checkedProductPackageWeights.includes(data.features.product_package_weights);
},