I have a form that I need to populate with JSON data. The form contains select, textarea, and input elements that need to be populated. The JSON data is complex / hierarchical (i.e. many nested objects).
I am aware of http://www.keyframesandcode.com/code/development/javascript/jquery-populate-plugin/ but it uses square bracket notation to map to field names (e.g.
<input name="person[name][last]" ...
I need to use dot notation though (e.g.
<input name="person.name.last" ...
I'm using jQuery so a jQuery solution is fine. Thanks.
Here's a hacked together alternative to populate using a recursive function:
function populator(json, nodes){
$.each(json, function(key, value){
newNodes = nodes ? nodes.slice() : [];
newNodes.push(key);
if (typeof(value)=="object") {
populator(value, newNodes);
else
$('name["' + newNodes.join('.') + '"]').val(value);
}
});
}
With this you can do:
populator({
person: {
name: {
last: 'Doe',
first: 'John'
},
address: {
street: '123 Main Street',
city: 'Montgomery',
state: 'AL'
}
});
Related
Ok I've got a list of objects, pretty standard.
const list = Immutable.List([{type:'thang',data:{id:'pants'}}]);
Now I want to change pants to shorts... so I'm thinking
list.setIn([0,'data','id'],'shorts');
Alas
Error: invalid keyPath
How is this done?
I can't even get this far despite messing around with this for a while :/ Once I know how to do this I'd like to know how to add a new element at a position
list.setIn([0,'data','length'],'short');
To add a new length attribute to the data object at position 0 in the list.
My bad. I was going wrong with the creation of the Immutable structure. If I change
const list = Immutable.List([{type:'thang',data:{id:'pants'}}]);
To
const list = Immutable.fromJS([{type:'thang',data:{id:'pants'}}]);
Then I can
list.setIn([0,'data','id'],'shorts');
Our nested structured data:
const state = {
Persons: [
{
fname: 'J.R.R',
lname: 'Tolkin',
},
{
fname: 'jack',
lname: 'London',
}
]
};
Requiring Immutable
const { fromJS } = require('immutable')
Turning simple object to Map
const stateMapped = fromJS(state);
Getting Data from nested structure
console.log(stateMapped.getIn(['Persons', 0, 'fname']))//output: J.R.R
setting data in nested structure
var objClone = stateMapped.setIn(['Persons', '0', 'fname'], 'John Ronald Reuel');
console.log('' + objClone.getIn(['Persons', 0, 'fname'])); //output: John Ronald Reuel
I would like to create a Form in ExtJS 5.0 completely based on a Store. Every store item represents a "line in the form". A "line" consists three or more form widgets.
Basically this is a search panel, where you define search conditions. Every condition consits of: FieldName selector, an operator selector, and a widget to write/select a condition operand. For example search for people with:
name starting with Joe (FieldName:name, operator:starting with, widget:textfield)
birtday before 1980.01.01. (FieldName:birthday, operator:before, widget:datepicker)
I get the conditions in JSON, and load them in a Store. I would like to dynamically generate the form based on this store, make modifications in the form, and ask the Store for a new JSON with the modifications (new conditions, etc).
I have problems with the first step: simply generate form widgets based on store content.
How can this be done?
I'm going to assume here that the JSON data represents a variety of dynamic data, and you can't simply use a pre-canned control like a grid, or a fixed form.
What you need to do is to make your own container class, which dynamically creates widgets based on the JSON content. You'll have to write this yourself, of course.
One extreme is to make your JSON content in the store be valid arguments to, say, Ext.widget - but that's probably not feasible, or even desirable.
For a more middling position, use the JSON data to determine, based on conditions, what widgets to add.
As a rough outline, you want something like this:
Ext.define('MyFormContainer', {
extend: 'Ext.form.FormPanel',
config: {
// A store or MixedCollection of JSON data objects, keyable by id.
formData: null
},
layout: 'vbox',
initComponent: function() {
this.callParent(arguments);
this.getFormData().each(this.addField, this)
},
addField: function(fieldData) {
var widgetConfig = this.buildWidgetConfig(fieldData);
this.add(widgetConfig);
},
buildWidgetConfig: function(fieldData) {
// The heart of the factory. You need a way to determine what sort of widget to make for
// the field. For the example config, a fieldset with three fields would probably be
// appropriate:
var fieldSet = { xtype: 'fieldset', layout: 'hbox' };
var items = [];
items[0] = { xtype: 'textfield', name: fieldData['FieldName'] };
// this would be a link to a custom widget to handle the operator. Or maybe you could
// just spit out text, if it's not meant to be alterable.
items[1] = { xtype: 'myoperator_' + fieldData['operator'], name: 'operator' };
items[2] = { xtype: fieldData['widget'], name: 'value' }
fieldSet.items = items;
return fieldSet;
}
})
This is a simple and contrived example, but it should (after you fill in the blanks, such as missing requires and the custom operator widgets) render a form based on the JSON data.
(I personally use this approach - with a great deal more sophistication that I can show in a simple example - to generate dynamic forms based on server-supplied form descriptions)
This should be a fairly simple one.
myobject has various properties, _id, name, createdBy, date etc
In my find query I want to only return specific fields from within myObject. So for example, what would I need to do to modify the find query below so that only name was returned?
myCollection.find({createdBy: someId}, {fields: {myObject: 1}}).fetch();
Currently this will return everything in myObject which it should do, I just want one field within myObject returned.
Here is a way to do it within the query:
myCollection.find({createdBy: someId}, {fields: {'myObject.name':
1}}).fetch();
Note the quotes around
'myObject.name'
Lets assume we are talking about posts, and a post document looks like this:
{
_id: 'abc123',
title: 'All about meteor',
author: {
firstName: 'David',
lastName: 'Weldon'
}
}
You can then extract all of the last names from all of the authors with this:
var lastNames = Posts.find().map(function(post) {
return post.author.lastName;
});
Modify the selector and options as needed for your collection. Using fields in this case may be a small optimization if you are running this on the server and fetching the data directly from the DB.
I am using https://github.com/felixge/node-mysql module with node.js.
Mysql table has a field of type POINT. The module requires to send array of arrays to insert bulk records. But It doesn't seem to have option to specify data type.
So naturally, the following gets enclosed in quotes
var loc = "GeomFromText('POINT(" + lat + "," + lon + ")')";
Has anybody tried this? How can I convince the query builder to treat this as an sql function?
Or do I have to make my own query builder?
There is a pull request from kevinhikaruevans that does it. You can do something like that to convert objects to points:
if (typeof val === 'object') {
if(val.hasOwnProperty('lat') && val.hasOwnProperty('long')) {
return 'POINT(' + [val.lat, val.long].map(parseFloat).join(',') + ')';
}
}
Supposing you have a table mytable with only the field point of type POINT, you would insert them like this:
var points = [
[{ lat: 1, long: 4}],
[{ lat: 23, long: -8.345}]
];
var query = connection.query('INSERT INTO mytable(point) VALUES ?', [points], your_callback_func);
console.log("Query: " + query.sql);
This will generate a query similar to:
INSERT INTO mytable(point)
VALUES (POINT(1,4)), (POINT(23,-8.345))
This would convert any object with both lat and long fields to a MySQL point. If this is not an intended behavior, you could create a Point class and use it instead of plain objects, and in lib/protocol/SqlString.js check if the value is an instance of Point.
Try constructing a query to handle POINT() and batch where site is an object with properties and values shown below. This approach works for me.
pool.query('INSERT INTO table SET geometryField = POINT(?,?), ?',[coords.lat,coords.lng,site], function(err, response) {
{ sitename: 'A Site',
customer: 'A Customer',
country: 'AL',
timezone: 'America/Los_Angeles',
address1: '123 My Street',
city: 'MyCity',
state: 'WA',
postalcode: '98110'}
I want to make a dynamic ng-grid , which adjusts its columns according to the key values in my JSON object. JSON object is fetched from an api. the problem I am facing is defining columns at runtime i.e The columns are not available at design time but will only be available only at runtime. I want to have something like :
http://plnkr.co/edit/q1Ye10OsIn9NOJmrICyD?p=preview
So that, I have as many columns as keys in my Json object. API's can vary so I need to make a grid which adjusts its columns.
My plunker is not working, but I hope it gives you idea, what I am trying to do.
Unless I'm misunderstanding what you want, you don't need to mess with columnDefines. Just having this:
faculty.controller('facultycontroller', function facultycontroller($scope, $http, $window){
$scope.facdata = [];
$scope.gridOptions = {
data: 'facdata'
};
$http.get("http://mtapi.azurewebsites.net/api/institute").then(function (result) {
$scope.facdata = result.data;
console.log($scope.facdata[0]);
});
});
will create the grid with a column for each key in your json.
Update
If you want to filter out any columns that begin with '$', you can do something like this:
angular.forEach(result.data[0], function(value, key){
if(key.indexOf('$') != 0)
$scope.columnDefines.push({ field: key, displayName: key});
});
Actually, you were close with what you were trying to do. You just need to put the columnDefines variable on $scope, and assign it to the gridOptions using a string, like this:
$scope.columnDefines = [];
$scope.gridOptions = {
data: 'facdata',
columnDefs: 'columnDefines'
};
Plunker
Try attaching your columnDefines variable to the scope ($scope.columnDefines). Then in your options do this:
$scope.gridOptions =
{
data: 'facdata',
columnDefs: 'columnDefines' //Note the quotes
};
This will make ng-grid watch your columnDefs for changes