using a backbone model to fill options of a select field - javascript

I would like to populate the options of a select field with the attributes from a "static" model. For example I have a Model and a collections of US states:
State = Backbone.Model.extend({
label:'',
value:''
}) ;
STATES = Backbone.Collection.extend({
model: State
});
states = [
{label: "Select ", value: '__' },
{label: "Alabama ", value: 'AL' },
{label: "Alaska ", value: 'AK' },
{label: "Arizona ", value: 'AZ' },
....];
localstates = new app.STATES(states); // or fetch the list of states from a RESTful site.
I then using back form have any address view and I want to pass localstates into the Form to populate the options of the state field:
UserAddress = Backform.Form.extend({
el: $("#personalInformation"),
fields: [
{name: "address1", label: "Address1", control: "input"},
{name: "address2", label: "Address2", control: "input"},
{name: "city", label: "City", control: "input"},
{name: "state", label: "State", control: "select",
options: **localstates**,
{name: "zip", label: "Zip Code", control: "input"},
{control: "button", label: "Save to server"}
],
});
I'm guessing I need to somehow pass the states collection into the User Address view and then access the attributes. But I have not been able to find a good example of how to do this.
edit1: Ok this is a bit silly in this case but:
newstate = new app.STATES(app.states);
var allstates =[];
app.newstate.forEach(function(state){
allstates.push({"label": state.get("label"), "value" : state.get("value")});
})
Gives me and array I can use at localstate. Basically I just re-created my original array in this case. In the case where it was fetch from a server it would be useful, but is there a better way?

You can do localstates.toJSON() to get a copy of the values to use in the template.
See Collection.toJSON()

Related

Javascript objects combining with Jquery?

I have an issue with manipulating data in Javascript/jQuery and I could use some help.
I have an array of objects that lools like this:
var projects = [
{title:'project1'},
{title:'project2'},
{title:'project3'},
];
I have another array of objects that looks like this:
ganttEvents = [
{
text: 'some text',
start_date: '2018/06/13',
end_date: '2018/06/14',
id: '1',
readonly: true,
project: 'project1',
category: 'scoping',
}
{
text: 'some text2',
start_date: '2018/06/14',
end_date: '2018/06/15',
id: '1',
readonly: true,
project: 'project2',
category: 'scoping',
}
{
text: 'some text3',
start_date: '2018/06/15',
end_date: '2018/06/16',
id: '1',
readonly: true,
project: 'project2',
category: 'design',
}
{
text: 'some text4',
start_date: '2018/06/13',
end_date: '2018/06/14',
id: '1',
readonly: true,
project: 'project2',
category: 'scoping',
}
{
text: 'some text5',
start_date: '2018/06/14',
end_date: '2018/06/15',
id: '1',
readonly: true,
project: 'project3',
category: 'testing',
}
{
text: 'some text6',
start_date: '2018/06/15',
end_date: '2018/06/16',
id: '1',
readonly: true,
project: 'project3',
category: 'build',
}
];
The project field in the second object will always be one of the objects in the first array.
I then need to end up with an object that looks like this:
source: [
{
name: "project1", // a project defined in the projects array
desc: "scoping", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/13", // the start_date from the ganttEvents array of objects
from: "2018/06/14", // the end_date from the ganttEvents array of objects
desc: "some text", // the text from the ganttEvents array of objects
label: "some text", // the text from the ganttEvents array of objects
}
]
},
{
name: "project2", // a project defined in the projects array
desc: "scoping", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/14",
from: "2018/06/15",
desc: "some text2",
label: "some text2",
},
{
to: "2018/06/13",
from: "2018/06/14",
desc: "some text4",
label: "some text4",
},
]
},
{
name: "project3", // a project defined in the projects array
desc: "testing", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/14",
from: "2018/06/15",
desc: "some text5",
label: "some text5",
}
]
},
{
name: "project3", // a project defined in the projects array
desc: "build", // the category from the ganttEvents array of objects
values: [
{
to: "2018/06/15",
from: "2018/06/16",
desc: "some text6",
label: "some text6",
}
]
},
]
There may be several values at all stages for each project and there maybe projects with no events at all that need to be omitted from the source object.
Please can you assist?
Edit:
The background behind this is that I am pulling a list of events from a SharePoint list using SharePointPlus. This results in the ganttEvents array. I need to plug this in to the jQuery.Gantt library which requires the events to be formatted in a particular way.
jQuery.Gantt
I am sorry but i am relatively new to Javascript (Python programmer usually) I have tried different methods of doing this to no avail.
You can use reduce to group the array into an object. Use the concatenated values of project and category as the key. Use Object.values to convert the object into an array.
var ganttEvents = [{"text":"some text","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project1","category":"scoping"},{"text":"some text2","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text3","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project2","category":"design"},{"text":"some text4","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text5","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project3","category":"testing"},{"text":"some text6","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project3","category":"build"}];
var result = Object.values(ganttEvents.reduce((c, v) => {
let k = v.project + "-" + v.category;
c[k] = c[k] || {name: v.project,desc: v.category,values: []};
c[k].values.push({to: v.end_date,from: v.start_date,desc: v.text,label: v.text});
return c;
}, {}));
console.log(result);
Without Object.values(), you can loop using for
var ganttEvents = [{"text":"some text","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project1","category":"scoping"},{"text":"some text2","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text3","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project2","category":"design"},{"text":"some text4","start_date":"2018/06/13","end_date":"2018/06/14","id":"1","readonly":true,"project":"project2","category":"scoping"},{"text":"some text5","start_date":"2018/06/14","end_date":"2018/06/15","id":"1","readonly":true,"project":"project3","category":"testing"},{"text":"some text6","start_date":"2018/06/15","end_date":"2018/06/16","id":"1","readonly":true,"project":"project3","category":"build"}];
var temp = ganttEvents.reduce((c, v) => {
let k = v.project + "-" + v.category;
c[k] = c[k] || {name: v.project,desc: v.category,values: []};
c[k].values.push({to: v.end_date,from: v.start_date,desc: v.text,label: v.text});
return c;
}, {});
var result = [];
for (var key in temp) result.push(temp[key]);
console.log(result);

How to use placeholder with Meteor AutoForm select2?

I am using the AutoForm package including the select2 extension for Meteor.
aldeed:autoform
aldeed:autoform-select2
The documentation on autoform-select2 tells me I can set use select2Options like this:
{{> afQuickField name='finalReviewerComments'select2Options=select2Options}}
My schema:
finalReviewerComments: {
type: String,
max: 20,
autoform: {
options: [
{label: "Good", value: 0},
{label: "9: Grammar/spelling/formatting/readability", value: 9},
{label: "8: Not a finding", value: 8},
{label: "7: Information missing", value: 7},
{label: "6: Repeated/combined finding", value: 6},
{label: "5: FAQ requirements", value: 5},
{label: "4: Multiple findings in one", value: 4},
{label: "3: Context missing", value: 3},
{label: "2: Country/page number error", value: 2},
{label: "1: Misinterpretation", value: 1}
],
type: "select2"
},
optional: true
}
I tried both adding this to my schema inside autoform:
afFieldInput: {
select2Options: {
placeholder: "Imaginary text here"
}
}
And using a helper function select2Options as pointed out in the docs:
Template.finalReview.helpers({
select2Options: function () {
return {placeholder: "Final Review Comments"};
}
});
Neither of the two options work. How can I get it to work? I want an empty select2 input box when the form is rendered.
EDIT: Just to clarify: {allowclear: true} didn't work either.
The placeholder is blank by default. To add an actual value, this works, as the documentation states:
Helper file:
Template.testTemplate.helpers({
select2Options: function () {
return {placeholder: "Find a dataset"};
}
})
Template file:
<template name="testTemplate">
{{#autoForm id='addDatasetForm' schema=datasetsSchema type='normal' class="form-horizontal" validation='keyup'}}
{{> afQuickField class='select2 select-css' name=dataset_name options=getDatasets size=10 select2Options=select2Options}}
{{/autoForm}}
</template>
It returns:
Although now that I have provided this answer, the placeholder appears to not show up the first time the template is rendered. This particular field is part of an array field, and it only shows up once I've removed and then re-added an element to the array field.

Backbone.View not responding to Backbone.UI

I'm building a small program to allow display of some details of a group of people. There is an option to update the details. However, the updates are not being rendered by the view:
Here is my server.js:
var express= require("express"),
bodyparser= require("body-parser");
var app= express();
app.use(express.static(__dirname+ "/public"));
app.use(bodyparser.json());
app.get("/", function(req, res){
res.render("index.jade");
});
app.listen(3002);
My index.jade is:
doctype html
link(rel="stylesheet", href="backbui.css")
#main
script(src= "jquery.js")
script(src= "underscore.js")
script(src= "backbone.js")
script(src= "laconic.js")
script(src= "moment.js")
script(src= "backbui.js")
script(src= "theapp.js")
My theapp.js file is:
var Person= Backbone.Model.extend({}),
People= Backbone.Collection.extend({});
var Genders= new Backbone.Collection(
[
{name: "Female", id: 1},
{name: "Male", id: 0}
]);
var people= new People([
{name: "John Doe", gender: Genders.get(0), birthday:
new Date(1990, 5, 15), married: false},
{name: "Jane Smith", gender: Genders.get(1), birthday:
new Date(1985, 10, 10), married: true},
{name: "Tom Smith", gender: Genders.get(0), birthday:
new Date(1980, 1, 20), married: true},
{name: "Sally Fox", gender: Genders.get(1), birthday:
new Date(1998, 7, 31), married: false}
]);
var table= new Backbone.UI.TableView({
model: people, // collection can also be passed
columns: [
{title: "Name", content: "name"},
{title: "Gender", content: "gender",
format: function(model){ return model.get("name"); }},
{title: "Birthday", content: "birthday",
format: function(date){ return date.toString(); }},
{title: "Married", content: "married",
format: function(married){ return married? "yes": "no"; }}
]
});
var sally= people.models[3];
var textbox= new Backbone.UI.TextField({
model: sally,
content: "name",
});
var radios= new Backbone.UI.RadioGroup({
model: sally,
content: "gender",
alternatives: Genders,
altLabelContent: "name",
});
var Appview= Backbone.View.extend({
el: "#main",
render: function(){
this.$el.append(table.render().el);
this.$el.append(textbox.render().el);
this.$el.append(radios.render().el);
return this;
}
});
new Appview().render();
I want to see real-time update of 4th name in the table viz. Sally Fox when I make changes in the textbox area. Similarly I would like to see the table gender of Sally Fox change when I make the change in the radio button.
Basically I want my Backbone.TableView to listen to changes made in other Backbone.UI widgets like Backbone.UI.RadioGroup and Backbone.UI.TextField
You're on the right path. Add listeners in your views to listen for when changes happen to the people collection. Changes to individual models (i.e. sally) will also bubble up through the collection.
I'm not too familiar with Backbone.UI, but the changes would go something like this:
// Make the table listen to changes in the passed-in collection & re-render
// when needed
var table= new Backbone.UI.TableView({
model: people, // collection can also be passed
columns: [
{title: "Name", content: "name"},
{title: "Gender", content: "gender",
format: function(model){ return model.get("name"); }},
{title: "Birthday", content: "birthday",
format: function(date){ return date.toString(); }},
{title: "Married", content: "married",
format: function(married){ return married? "yes": "no"; }}
],
initialize: function() {
// When a change event happens to the model/collection, re-render
this.listenTo(model, 'change', this.render);
}
});
You would do similar things for other views that you want to react to data changes. The key is to have the views share the same instance of the model/collections you're changing, and then listen for specific changes.
If this doesn't get you going, post comments and/or a JSFiddle and we can make progress that way.
While the answer given by Peter (above) is also correct, we can also make the changes directly in the backbone-ui.js library file:
Inside the initialize method for tableview (search for tableview in the file backbone-ui.js, find its initialize function) add:
this.model.on("change", this.render, this);
and you'll be fine.
(You may want to add the same line inside the initialize method of the list property of backbone-ui.js file to get responsive views for lists)

Angular JS replace values ng grid

I am newbie in angular JS and I think that I need help.
This is my issue :
I have a ng-grid which is linked with a table. Within there are values and a ID (which is a foreignkey from a another table). I don't want to show the ID but another field in this foreign table.
CompanyFactory.getCompanies().success(function (data) { $scope.objs = data })
$scope.gridOptions = {
data: 'objs',
showGroupPanel: true,
jqueryUIDraggable: true,
columnDefs: [
{ field: 'COMP_NAME', displayName: 'comp_name'},
{ field: 'COUNTRY', displayName: 'country' },
{ field: 'LU_SECTOR_ID', displayName: 'sector', },
]
};
I want show the sector_name field instead of the sector_ID field. How can I make the relation between these two tables ?
$scope.countries = [
{ COMP_NAME: 'KOLI', COUNTRY: 'KOLI_COUNTRY', LU_SECTOR_ID: '1'},
{ COMP_NAME: 'ZOLI', COUNTRY: 'ZOLI_COUNTRY', LU_SECTOR_ID: '2'},
{ COMP_NAME: 'TULI', COUNTRY: 'TULI_COUNTRY', LU_SECTOR_ID: '3'},
];
$scope.sector= [
{ LU_SECTOR_ID: '1', LU_SECTOR_NAME: 'SECTOR_1'},
{ LU_SECTOR_ID: '2', LU_SECTOR_NAME: 'SECTOR_2'},
{ LU_SECTOR_ID: '3', LU_SECTOR_NAME: 'SECTOR_3'},
];
I would like to show in the ng-grid the SECTOR NAME instead of the SECTOR_ID.
It is difficult to answer the question without the information of the data object.
However, suppose that your data object returned by your CompanyFactory is something like:
[
{
"COMP_NAME": "Tomms",
"COUNTRY": "France",
"LU_SECTOR_ID": "9":,
"SECTOR": { "SECTOR_NAME": "IT" }
}
]
You just need to bind the correct field:
$scope.gridOptions = {
data: 'objs',
showGroupPanel: true,
jqueryUIDraggable: true,
columnDefs: [
{ field: 'COMP_NAME', displayName: 'comp_name'},
{ field: 'COUNTRY', displayName: 'country' },
// Here
{ field: 'SECTOR.SECTOR_NAME', displayName: 'sector', },
]
};
But, if you returning both objects separated you will need to link it manually. My suggestion is to perform that in the server side and return the object like I used as an example.
the problem is here
{ field: 'LU_SECTOR_ID', displayName: 'sector', }
Specifically
LU_SECTOR_ID
you need to change the name of this variable to be the name on the objs and not the id

Populating KendoGrid with JSON objects

Being very new to Kendo UI and Knockout (3 days!), I'm trying to convert a legacy Java applet to Javascript. So far, creating and binding the kendoGrid was relatively easy:
function JobViewModel() {
var self = this;
self.jobData = new ko.observableArray([]);
self.grdJobs = {
scrollable: true,
sortable: true,
filterable: false,
columnMenu: true,
resizable: true,
columns: [
{ title: "Job ID", field: "jobID" },
{ title: "Owner", field: "owner" },
{ title: "Description", field: "description" },
{ title: "State", field: "runState" },
{ title: "Start Time", field: "timeStart" },
{ title: "End Time", field: "timeEnd" },
{ title: "Elapsed Time", field: "timeElapsed" },
{ title: "Progress", field: "progress" },
{ title: "Agent", field: "agent" },
{ title: "Last Action", field: "lastAction" }
],
selectable: "single"
};
};
The data coming back from the server are an array of JSON objects (of any length) something like the following (shortened for brevity):
[{0: 1, 2: 3, 4: 5, ...}, {0: 1, 2: 21, 4: 5, ...}, {0: 1, 2: 23, 4: 5, ...}]
This array of objects which are numeric key/value pairs are mapped to a dictionary object where the numeric keys are paired with string values something like:
{
0: "State"
1: "Finished"
2: "JOB ID"
3: "54759"
4: "Owner"
5: "John"
...
21: "54758"
...
23: "54757"
...
}
What I need to get is the mapped strings from the dictionary as they relate to the array of JSON objects. The approach I tried was to JSON.stringify(obj[i]) but then I wasn't sure what I could do with it (maybe use it in a ko.observable that could be assigned to the kendoGrid?) Anyway, what I'm after based on the sample data I've shown above is a grid with column headers "JOB ID", "Owner", and "State" and 3 rows of jobs (54757, 54758, 54759) all owned by John and State Finished.
I hope this all made sense. I guess what I really need is how to take JSON and convert it into something usable that can be populated into a Kendo Grid. Thanks for helping out a JS/JSON/Kendo/Knockout neophyte!
You could try to map those two arrays you have to another array with elements you can use.
I made a simple jsFiddle to demonstrate this: jsFiddle
The code is pretty straight forward:
var data = [{ 0: 1, 2: 3 }, { 0: 4, 2: 3 }];
var mapping = { 0: 'State', 1: 'Finished', 2: 'Owner', 3: 'John', 4: 'Pending' };
var realData = [];
$.each(data, function(index, obj) {
var arrayElem = {};
$.each(obj, function(key, value) {
arrayElem[mapping[key]] = mapping[value];
});
realData.push(arrayElem);
});

Categories

Resources