Backbone Relational - Deep nested models/collections - javascript

Having some fun with Backbone-relational.js v0.10.0
I have a JSON object which contains nested models and collections, to keep this simple I have made the example below. A company can have many employees, employees can have one address and many tasks.
{
name: 'Nicks Company',
employees: [{
name: 'Bob',
address: {
line1: '1 City Lane',
city: 'London'
},
tasks: [{
description: 'Make this work'
}]
}, {
name: 'Bill',
address: {
line1: '1 The Street',
city: 'Birmingham'
},
tasks: [{
description: 'Make a cake'
}, {
description: 'Fix all the things'
}]
}]
}
In the below JSFiddle (console) you can see that the address is a plain object, also the commented out code for tasks has been disabled as tasks is returned as an array.
JSFiddle: https://jsfiddle.net/nwa29uLv/2/
Neither the address model or the collection of tasks are created as Backbone instances, is this possible or am I pushing the limits of this plugin?

Here is how I resolved the issue. You were missing the
reverseRelation.
BTW did you look at this post? It has a similar issue.
Follow the fiddle here
var Address = Backbone.RelationalModel.extend({});
var Task = Backbone.RelationalModel.extend({});
var TaskCollection = Backbone.Collection.extend({
model: Task
});
var Employee = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasOne,
key: 'address',
relatedModel: Address,
reverseRelation: {
type: Backbone.HasOne,
key: 'employee'
}
}, {
type: Backbone.HasMany,
key: 'tasks',
collectionType: TaskCollection,
relatedModel: Task,
reverseRelation: {
type: Backbone.HasOne,
key: 'operatesOn'
}
}]
});
var EmployeeCollection = Backbone.Collection.extend({
model: Employee
});
var Company = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasMany,
key: 'employees',
relatedModel: Employee,
reverseRelation: {
key: 'worksFor'
}
}]
});
var company = new Company({
name: 'Nicks Company',
employees: [{
name: 'Bob',
address: {
line1: '1 City Lane',
city: 'London'
},
tasks: [{
description: 'Make this work'
}]
}, {
name: 'Bill',
address: {
line1: '1 The Street',
city: 'Birmingham'
},
tasks: [{
description: 'Make a cake'
}, {
description: 'Fix all the things'
}]
}]
});
console.log('Company:', company.get('name'));
company.get('employees').each(function(employee) {
console.log('Employee:', employee.get('name'));
console.log('Employee:', employee.get('name'), 'Address Model:', employee.get('address').get('city'));
employee.get('tasks').each(function(task) {
console.log('Employee:', employee.get('name'), 'Task: ', task.get('description'));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone-relational/0.10.0/backbone-relational.js"></script>

Related

Destructuring object consist of deep nested object of arrays

I'm trying to destructure setup shown below. I need to get text: Zelena The Wicked Witch is an enemy to Emma Swan in Once Upon a Time.
OK, it's easy to get properties from objects info and protagonist, but I can't get data from an array of objects (enemies) for particular object, for instance for row number 3.
I tried many different expressions, with no luck.
Any help would be highly appreciated.
function nestedArrayAndObject() {
// refactor this to a single line of destructuring...
const info = {
title: 'Once Upon a Time',
protagonist: {
name: 'Emma Swan',
enemies: [
{name: 'Regina Mills', title: 'Evil Queen'},
{name: 'Cora Mills', title: 'Queen of Hearts'},
{name: 'Peter Pan', title: `The boy who wouldn't grow up`},
{name: 'Zelena', title: 'The Wicked Witch'},
],
},
}
const {
protagonist: {
enemies[3]: {name: enemyName}
},
protagonist: {
enemies: {title: enemyTitle}
},
protagonist: {name: protagonistName},
title: title
} = info;
return `${enemyName} (${enemyTitle}) is an enemy to ${protagonistName} in "${title}"`
}
nestedArrayAndObject();
It's not that hard. Take a look at this.
const info = {title: 'Once Upon a Time', protagonist: {name: 'Emma Swan', enemies: [ {name: 'Regina Mills', title: 'Evil Queen'}, {name: 'Cora Mills', title: 'Queen of Hearts'}, {name: 'Peter Pan', title: 'The boy who wouldn\'t grow up'}, {name: 'Zelena', title: 'The Wicked Witch'} ]}};
const {protagonist: {enemies: [,, {name, title}]}} = info;
console.log(name, title)
You can achieve as:
const {
title,
protagonist: {
name: protagonistName,
enemies: [, , , { name: enemyName, title: enemyTitle }],
},
} = info;
function nestedArrayAndObject() {
// refactor this to a single line of destructuring...
const info = {
title: 'Once Upon a Time',
protagonist: {
name: 'Emma Swan',
enemies: [
{ name: 'Regina Mills', title: 'Evil Queen' },
{ name: 'Cora Mills', title: 'Queen of Hearts' },
{ name: 'Peter Pan', title: `The boy who wouldn't grow up` },
{ name: 'Zelena', title: 'The Wicked Witch' },
],
},
};
const {
title,
protagonist: {
name: protagonistName,
enemies: [, , , { name: enemyName, title: enemyTitle }],
},
} = info;
return `${enemyName} (${enemyTitle}) is an enemy to ${protagonistName} in "${title}"`;
}
nestedArrayAndObject();

Arrange Array by Given another array property as order in javascript [duplicate]

This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 5 years ago.
I have here 2 array's
1st array is the main data and
2nd array by property it must be the bases of 1st array data orders.
2nd array sample :
var order_basis = [
{ tag:'vip' }, { tag:'home' } { tag:'work' }
]
1st array data
var main_data = [
{ tag:'work',name:'sample',contact:'0987654',email:'sample#email.com' },
{ tag:'home',name:'sample',contact:'0987654',email:'sample#email.com' },
{ tag:'home',name:'sample',contact:'0987654',email:'sample#email.com' },
{ tag:'work',name:'sample',contact:'0987654',email:'sample#email.com' },
{ tag:'vip',name:'sample',contact:'0987654',email:'sample#email.com' },
]
expected output is
base on the 2nd array tag order it must be ..
ReOrder( main_data ,order_basis ){
//main code
return
}
result is
tag:'vip' name:'sample' contact:'0987654' email:'sample#email.com'
tag:'home' name:'sample' contact:'0987654' email:'sample#email.com'
tag:'home' name:'sample' contact:'0987654' email:'sample#email.com'
tag:'work' name:'sample' contact:'0987654' email:'sample#email.com'
tag:'work' name:'sample' contact:'0987654' email:'sample#email.com'
Thank you for helping mate! ..
You could take the index of the tags of order_basis assortorder by using an object with this data.
var order_basis = [{ tag: 'vip' }, { tag: 'home' }, { tag: 'work' }],
main_data = [{ tag: 'work', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'home', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'home', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'work', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'vip', name: 'sample', contact: '0987654', email: 'sample#email.com' }],
order = {};
order_basis.forEach(function (o, i) { order[o.tag] = i + 1 });
main_data.sort(function (a, b) {
return order[a.tag] - order[b.tag];
});
console.log(main_data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can sort the main function based on the order_basis array.
function getFormatted(main, order_basis){
order_basis = order_basis.map(x => x.tag);
return main.sort(function(a, b){
if(order_basis.indexOf(a.tag) > order_basis.indexOf(b.tag))
return 1;
return -1;
});
}
var order_basis = [{ tag: 'vip' }, { tag: 'home' }, { tag: 'work' }],
main_data = [{ tag: 'work', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'home', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'home', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'work', name: 'sample', contact: '0987654', email: 'sample#email.com' }, { tag: 'vip', name: 'sample', contact: '0987654', email: 'sample#email.com' }];
console.log(getFormatted(main_data, order_basis));
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to iterate through an array of object properties, in an array of objects

I have an array of objects, that looks like this:
data = [
{
title: 'John Doe',
departments: [
{ name: 'Marketing', slug: 'marketing'},
{ name: 'Sales', slug: 'sales'},
{ name: 'Administration', slug: 'administration'},
]
},
{
title: 'John Doe Junior',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Sales', slug: 'sales'},
]
},
{
title: 'Rick Stone',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Marketing', slug: 'marketin'},
]
},
]
How can I iterate over each object's departments array and create new arrays where I would have employees sorted by departments, so that the end result would like this:
operations = [
{
title: 'John Doe Junior',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Sales', slug: 'sales'},
]
},
{
title: 'Rick Stone',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Marketing', slug: 'marketin'},
]
},
]
marketing = [
{
title: 'John Doe',
departments: [
{ name: 'Marketing', slug: 'marketing'},
{ name: 'Sales', slug: 'sales'},
{ name: 'Administration', slug: 'administration'},
]
},
{
title: 'Rick Stone',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Marketing', slug: 'marketin'},
]
},
]
What would be the way to create dynamically this kind of arrays?
Update
I have tried to come up with a solution using the suggestion from the answer, where I would dynamically create an array with department objects that would have an array of employees:
const isInDepartment = departmentToCheck => employer => employer.departments.find(department => department.slug == departmentToCheck);
var departments = [];
function check(departments, name) {
return departments.some(object => name === object.department);
}
employees.forEach((employee) => {
employee.departments.forEach((department) => {
let found = check(departments, department.slug);
if (!found) {
departments.push({ department: department.slug });
}
});
});
departments.forEach((department) => {
// push an array of employees to each department
//employees.filter(isInDepartment(department));
});
But, I don't know how can I push the array of employees to the object in the array that I am looping at the end?
This is the fiddle.
How about this? I use Array.protoype.filter operation, and I use a higher-order function (in this case a function that returns a function) to create the predicate (function that returns a boolean) that will check whether an employee is in a specific department. I added some (hopefully) clarifying comments in the code.
Edit: with the new code and context you provided this JSFiddle demo shows how it would work together.
const employees = [
{
title: 'John Doe',
departments: [
{ name: 'Marketing', slug: 'marketing'},
{ name: 'Sales', slug: 'sales'},
{ name: 'Administration', slug: 'administration'}
]
},
{
title: 'John Doe Junior',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Sales', slug: 'sales'}
]
},
{
title: 'Rick Stone',
departments: [
{ name: 'Operations', slug: 'operations'},
{ name: 'Marketing', slug: 'marketin'}
]
}
];
// given a department, this returns a function that checks
// whether an employee is in the specified department
// NOTE: the "find" returns the found object (truthy)
// or undefined (falsy) if no match was found.
const isInDepartment =
departmentToCheck =>
employee => employee.departments.find(dep => dep.name == departmentToCheck);
const employeesInMarketing = employees.filter(isInDepartment('Marketing'));
const employeesInOperations = employees.filter(isInDepartment('Operations'));
console.log('Employees in marketing', employeesInMarketing);
console.log('Employees in operations', employeesInOperations);

Sencha touch Selectfield picker not showing correct selection

Store of the selectfield contains same word with different case like Ed & ed.When we select ed,In the picker it is showing Ed.
Code:
Ext.create('Ext.form.Panel', {
fullscreen: true,
items: [
{
xtype: 'fieldset',
title: 'Select',
items: [
{
xtype: 'selectfield',
label: 'Choose one',
displayField:'firstName',
valueField:'firstName',
store:Ext.create("Ext.data.Store", {
fields: [
{name: 'firstName', type: 'string'},
],
data : [
{firstName: "Ed"},
{firstName: "ed"},
{firstName: "Tommy"},
{firstName: "Aaron"},
{firstName: "Jamie"}
]
})
}
]
}
]
});
Fiddle for the problem
In Sencha, the selectfield is somethings whose value doesn't distinguish between the caps and small letter. So, it has provided valuefield. If you create your store like this below, you will get the expected result:
store: Ext.create("Ext.data.Store", {
fields: [{
name: 'firstName',
type: 'string'
}, {
name: 'value',
type: 'string'
}],
data: [{
firstName: "Ed",
value: 'edCaps'
}, {
firstName: "ed",
value: 'edSmall'
}, {
firstName: "Tommy",
value: 'tommy'
}, {
firstName: "Aaron",
value: 'aaron'
}, {
firstName: "Jamie",
value: 'jamie'
}]
})
Here is fiddle also. Happy coding! :)

Retrieve from the store for time and set it to minvalue

var userStore = Ext.create('Ext.data.Store', {
model: 'User',
data: [
{ name: 'Lisa', phone: '555-111-1224', timecallval: '08:10' },
{ name: 'Bart', phone: '555-222-1234', timecallval: '09:54' },
{ name: 'Homer', phone: '555-222-1244', timecallval: '20:00' },
{ name: 'Marge', phone: '555-222-1254', timecallval: '08:11' }
]
});
var panel = Ext.create('Ext.form.Panel', {
items: [
{
xtype: 'timefield',
name: 'timecall',
id: 'timecall',
minvalue: '08:00'
// 08:00 to be changed to timecall value dynamically
}
}
I have searched for quite awhile but i don't seem to be able to set minvalue as the value retrieved from store. The problem is I want timefield to display 08:10, 09:54, 20:00 and 08:11 for selection. Any helpers?
Found the answer
Ext.getCmp('reserveEndTime').setMaxValue(selectrow.get('timecall'));

Categories