Referencing an object array for cascading select options with angular-formly - angular-formly

I'm creating a form which will have field options dependent upon choices earlier in the form, referencing a JSON array. I've studied the Cascade Select example, but haven't quite wrapped my head around how the controllers work in it. Would someone mind helping me adapt the concepts of the Cascade Select example to reference a JSON array?
Here is a link to a JS Bin illustrating what I'm trying to accomplish (be sure to "Run with JS"). I would like fields whose options are populated with respect to an array and are filtered based on previous selection. I've figured out how to do the first level of options for selecting a sport with a simple for-loop function passed to the "options" argument in the form element; but I need a hand moving to the next stage. Ideally, I would like to have more depth; i.e. Pick a Sport > Pick a Team > Pick a Player; but I should be able to figure it out with just the first filtered select options.
Thank you!

Actually this is totally unrelated to angular-formly. Your data model is not properly modeled, you should use the concept of foreign keys. A more appropriate modeling would be:
var sports = [{
id: 1,
name: 'Soccer'
}, {
id: 2,
name: 'Basketball'
}];
var teams = [{
id: 1,
fk: 1,
name: 'Bayern Munich'
}, {
id: 2,
fk: 1,
name: 'Real Madrid'
}, {
id: 3,
fk: 2,
name: 'Cleveland'
}];
var player = [{
id: 1,
fk: 1,
name: 'Mario Götze'
}, {
id: 1,
fk: 2,
name: 'Javier Hernandez'
}, {
id: 2,
fk: 3,
name: 'LeBron James'
}];
A working example is shown here: http://output.jsbin.com/jinaca

Related

And condition on Join table on the same field multiple times in Sequelize NodeJS?

I have one table called Users. One user can be present on multiple Email Group.
User Table
id, name
1, Sudhir Roy
2, Rahul Singh
Email Group Table
id, emailType, userID
1, Promotional, 1
2, Advertisement, 2
3, Advertisement, 1
Need to get all users based on Email Type. (Email type is dynamic and send in array form like ["Promotional", "Advertisement"]
How can we find users based on the emailGroup.
["Advertisement"] return [1, 2] from user table
["Advertisement", "Promotional"] return [1] from user table.
I tried to use [Op.and] and [Op.in]. Both are not working.
Here is my sample code.
const user = User.findAll({
where: {
"$emailGroup.emailType$": {
[Op.in]: emailGroup // Array from client
},
},
include: {
model: EmailGroup
}
})
It works well when the email group array is single but not working when we try to find more than one email group.
You can also add where clauses to the include object.
The resulting findAll would then become:
const user = User.findAll({
include: [
{
model: EmailGroup,
where: {
emailType$: {
[Op.in]: emailGroup, // Array from client
},
},
},
],
});
As shown here in the docs: https://sequelize.org/v5/manual/querying.html#relations---associations

Add two more keys and values to a requested array of objects with the same values?

I'm using Node.js to make a Axios request to the Vimeo API.
I'm kind of a Noob with Json but I'd like to understand. I made a call to Vimeo with a filter of name, so I get an "array of objects" (I hope that name is correct ) it looks like this below:
[{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' } ] }
This is simply the names of the videos, however I need to add two keys value pairs with the same value as the name value for a dropdown menu, so it looks like this below:
[{ name: 'A Personalized Goal for Anthony',
"text": "A Personalized Goal for Anthony",
"value": "A Personalized Goal for Anthony" },
{ name: 'Flow access & overview',
"text": "Flow access & overview"
"value": "Flow access & overview" },
{ name: 'Welcome - 2018 Conference',
"text": "Welcome - 2018 Conference"
"value": "Welcome - 2018 Conference" },
{ name: 'Dropout Video',
"text": "Welcome - 2018 Conference"
"value": "Welcome - 2018 Conference" }]
My app needs the keys "Text" and "Value" for a dropdown menu in order to process the response from the user.
I'm not sure why { name: 'Dropout Video'}, isn't formatted like this {"name":"Dropout Video"},
Is there a way in Node.js to add or duplicate an array using map or push using the same name value while also doing a foreach to this array which reflects the name but with two additional key value pairs with the same Value as the key Name?
This is a dynamic Object as well so when the request is called again it could have many more than just 4 video names returned.
My goal is to add numerous Videos to a Vimeo Album that I want to make the request to, then my app ( Slack chatbot ) then returns a list of options via a drop down menu for the users consideration so that I'm able to see which Name or title they selected and thus want more information on.
Thank you so much any help here. I wish Vimeo had a Text and Value field so I could just filter that instead but then it wouldn't be fun :)
You could map through your result, so, for example, after you get the result:
const movies = [{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' }];
You could map it to add the other two properties to each one of your objects, the advantage is that you are not mutating your results.
const mappedMovies = movies.map(movie => {
return {
name: movie.name,
text: movie.name,
value: movie.name
}
);
In that way, you will have the list of objects with the format that you want, now if you need it in json format you could do:
const JSONString = JSON.stringify(mappedMovies);
Objects are references, so you could just loop through your objects and add the keys.
const videos = [
{ name: 'A Personalized Goal for Anthony' },
{ name: 'Flow access & overview' },
{ name: 'Welcome - 2018 Conference' },
{ name: 'Dropout Video' }
]
for (video of videos) {
video.text = video.name
video.value = video.name
}
console.log(videos)
Welcome to SO Kevin,
It looks like you almost provided the answer yourself already...
To get the resulting array you can map through the object and add keys as required:
const slackVideos = videos.map(function (item, label) {
return {
...item, //this ensures all original keys are available, using the ES6 destructuring
text: item.name,
value: item.value,
}
});
Assuming videos is the object received from vimeo, slackVideos will now contain your aditional text & value keys; both containing the name key from the original vimeo object.

Replacing an object in an object array in Redux Store using Javascript/Lodash

I have an object array in a reducer that looks like this:
[
{id:1, name:Mark, email:mark#email.com},
{id:2, name:Paul, email:paul#gmail.com},
{id:3,name:sally, email:sally#email.com}
]
Below is my reducer. So far, I can add a new object to the currentPeople reducer via the following:
const INITIAL_STATE = { currentPeople:[]};
export default function(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_PERSON:
return {...state, currentPeople: [ ...state.currentPeople, action.payload]};
}
return state;
}
But here is where I'm stuck. Can I UPDATE a person via the reducer using lodash?
If I sent an action payload that looked like this:
{id:1, name:Eric, email:Eric#email.com}
Would I be able to replace the object with the id of 1 with the new fields?
Yes you can absolutely update an object in an array like you want to. And you don't need to change your data structure if you don't want to. You could add a case like this to your reducer:
case UPDATE_PERSON:
return {
...state,
currentPeople: state.currentPeople.map(person => {
if (person.id === action.payload.id) {
return action.payload;
}
return person;
}),
};
This can be be shortened as well, using implicit returns and a ternary:
case UPDATE_PERSON:
return {
...state,
currentPeople: state.currentPeople.map(person => (person.id === action.payload.id) ? action.payload : person),
};
Mihir's idea about mapping your data to an object with normalizr is certainly a possibility and technically it'd be faster to update the user with the reference instead of doing the loop (after initial mapping was done). But if you want to keep your data structure, this approach will work.
Also, mapping like this is just one of many ways to update the object, and requires browser support for Array.prototype.map(). You could use lodash indexOf() to find the index of the user you want (this is nice because it breaks the loop when it succeeds instead of just continuing as the .map would do), once you have the index you could overwrite the object directly using it's index. Make sure you don't mutate the redux state though, you'll need to be working on a clone if you want to assign like this: clonedArray[foundIndex] = action.payload;.
This is a good candidate for data normalization. You can effectively replace your data with the new one, if you normalize the data before storing it in your state tree.
This example is straight from Normalizr.
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
Can be normalized this way-
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
},
users: {
1: {
id: 1,
name: 'Dan'
}
}
}
}
What's the advantage of normalization?
You get to extract the exact part of your state tree that you want.
For instance- You have an array of objects containing information about the articles. If you want to select a particular object from that array, you'll have to iterate through entire array. Worst case is that the desired object is not present in the array. To overcome this, we normalize the data.
To normalize the data, store the unique identifiers of each object in a separate array. Let's call that array as results.
result: [1, 2, 3 ..]
And transform the array of objects into an object with keys as the id(See the second snippet). Call that object as entities.
Ultimately, to access the object with id 1, simply do this- entities.articles["1"].
If you want to replace the old data with new data, you can do this-
entities.articles["1"] = newObj;
Use native splice method of array:
/*Find item index using lodash*/
var index = _.indexOf(currentPeople, _.find(currentPeople, {id: 1}));
/*Replace item at index using splice*/
arr.splice(index, 1, {id:1, name:'Mark', email:'mark#email.com'});

mongoose updating a specific field in a nested document at a 3rd level

mongoose scheme:
var restsSchema = new Schema({
name: String,
menu: mongoose.Schema.Types.Mixed
});
simplfied document:
{
name: "Dominos Pizza",
menu:{
"1":{
id: 1,
name: "Plain Pizza",
soldCounter: 0
},
"2":{
id: 2,
name: "Pizza with vegetables",
soldCounter: 0
}
}
}
I'm trying to update the soldCounter when given a single/array of "menu items" (such as "1" or "2" objects in the above document) as followed:
function(course, rest){
rest.markModified("menu.1");
db.model('rests').update({_id: rest._id},{$inc: {"menu.1.soldCounter":1}});
}
once this will work i obviously will want to make it more generic, something like: (this syntax is not working but demonstrate my needs)
function(course, rest){
rest.markModified("menu." + course.id);
db.model('rests').update({_id: rest._id},{$inc:{"menu.+"course.id"+.soldCounter":1}});
}
any one can help with this one?
I looked for an answer but couldn't find nothing regarding the 3rd level.
UPDATE:
Added id to the ducument's subDocument
I think you want add all ids into sub-document, one way you can do as following.
Rest.find({_id: rest._id}, function(err, o) {
// add all ids into sub-document...
Object.keys(o.menu).forEach(function(key) {
o.menu[key].id = key;
});
o.save(function(err){ ... });
});
It seems you want to operate the key in query, I am afraid you cannot do it in this way.
Please refer to the following questions.
Mongodb - regex match of keys for subobjects
MongoDB Query Help - query on values of any key in a sub-object

Multiline unbuffered code in jade templates

I am trying to write a template that renders a double indexed array. So I started writing this:
- var grid = [[1, 0, 1], [0, 1, 0]];
each row in grid
each cell in row
if cell
span x
else
span o
but this is not how I want to write my array
I want to write it like this:
- var grid = [[1, 0, 1],
[0, 1, 0]];
This doesn't work because jade is already out of the inline javascript
- var grid = [[1, 0, 1],
- [0, 1, 0]];
This doesn't work because jade considers those two incorrect lines instead of one line
How can I make it work?
Update: Multiline defs are now working for me using Jade 1.11.0. Even nested JSON now works like a charm.
-
projects = [{
title: "Project 1",
classname: "project1",
slides: [{
title: "Slide 1"
img: "images/hello.png"
},{
title: "Slide 2"
img: "images/world.png"
}]
}, {
title: "Project 2",
classname: "project2",
slides: [{
title: "Slide 3"
img: "images/fun.png"
},{
title: "Slide 4"
img: "images/things.png"
}]
}]
EDIT: Yay, these are real! Go check out the other answer on how to pull this off.
Sadly, this is currently not possible in Jade. TJ (the maintainer) has stated that he does not care about this, but would welcome a feature request. https://github.com/visionmedia/jade/issues/796
Fortunately, you can declare the array in your JS file and pass it as a variable to Jade.

Resources