Ember-data multi-word model fields not serialized properly - serialization

I'm seeing some odd behavior with some custom serializer code that I wrote.
I have a field in an Asset model called 'marketName'. My Rails backend expects this field to be called 'market_name'. I've extended the ActiveModelSerializer and have overridden the 'extractSingle' and 'serialize' methods.
The odd thing is this - for all the other fields in my Asset model that are not made up of multiple words - the serialization code that I've written works great. No issues. However - for any field containing multiple words - the serialization doesn't work completely, in that while it saves the Asset when created - it doesn't correctly populate the Asset model's 'marketName' field (and any other field that is made up of multiple words).
For example if I examine the 'marketName' field in the data inspector it appears as '{}'. If I change the name of any multi word field in my Asset model to be singular (aka change 'marketName' to 'name') and update the serialization code accordingly - everthing works great.
Any idea what's going on ?
Thanks
Dave

In the test of extractSingle() that the core team (see line 126, also show below incase link goes bad for future readers) did, they pass in the variables as super_villains, then later the normalize() included in ActiveModelSerializer changes it for them to superVillains.
So I think in your extractSingle assume the values are not yet camelCase, but still are still in underscore_format (e.g., "market_name"), and you should be golden!
test("extractSingle", function() {
env.container.register('adapter:superVillain', DS.ActiveModelAdapter);
var json_hash = {
home_planet: {id: "1", name: "Umber", super_villain_ids: [1]},
super_villains: [{
id: "1",
first_name: "Tom",
last_name: "Dale",
home_planet_id: "1"
}]
};
var json = env.amsSerializer.extractSingle(env.store, HomePlanet, json_hash);
deepEqual(json, {
"id": "1",
"name": "Umber",
"superVillains": [1]
});
env.store.find("superVillain", 1).then(async(function(minion){
equal(minion.get('firstName'), "Tom");
}));
});

Related

OpenUI5 sap.m.Input Currency Formatting

This looks to be answered many different times but I can't seem to get it working with my implementation. I am trying to format and limit the data in a sap.m.Input element. I currently have the following:
var ef_Amount = new sap.m.Input({
label: 'Amount',
textAlign: sap.ui.core.TextAlign.Right,
value: {
path: '/amount',
type: 'sap.ui.model.type.Currency'
}
});
The first problem is that it kind of breaks the data binding. When I inspect the raw data (with Fiddler) submitted to the server it is an array like this:
"amount": [1234.25,null]
The server is expecting a single number and as such has issues with the array.
When I use the following, the binding works as desired but no formatting is performed.
var ef_Amount = new sap.m.Input({
label: 'Amount',
textAlign: sap.ui.core.TextAlign.Right,
value: '{/amount}'
});
The second problem is that the data entered is not limited to numbers.
I have tried using sap.m.MaskedInput instead but I don't like the usage of the placeholders because I never know the size of the number to be entered.
And lastly, it would be nice if when focus is placed on the input field, that all formatting is removed and re-formatted again when focus lost.
Should I be looking into doing this with jQuery or even raw Javascript instead?
Thank you for looking.
the array output is a normal one according to documentation. So you need to teach your server to acccept this format or preprocess data before submission;
this type is not intended to limit your data input;
good feature, but ui5 does not support this, because the Type object has no idea about control and it's events like "focus" it only deals with data input-output. So you have to implement this functionality on your own via extending the control or something else.
I would suggest using amount and currency separately. It's likely that user should be allowed to enter only valid currency, so you can use a combobox with the suggestions of the available currencies.
So, after much work and assistance from #Andrii, I managed to get it working. The primary issue was that onfocusout broke the updating of the model and the change event from firing. Simply replacing onfocusout with onsapfocusleave took care of the issues.
The final code in the init method of my custom control:
var me = this;
var numberFormat = sap.ui.core.NumberFormat.getCurrencyInstance({maxFractionDigits: 2});
me.addEventDelegate({
onAfterRendering: function() {
// for formatting the figures initially when loaded from the model
me.bindValue({
path: me.getBindingPath('value'),
formatter: function(value) {
return numberFormat.format(value);
}
});
},
onfocusin: function() {
// to remove formatting when the user sets focus to the input field
me.bindValue(me.getBindingPath('value'));
},
onsapfocusleave: function() {
me.bindValue({
path: me.getBindingPath('value'),
formatter: function(value) {
return numberFormat.format(value);
}
});
}
});

ExtJS (4.1) creating static data store

I am no JS star so I'm having trouble finding a solution to something that is probably easier than I know.
the page loads, but the ui content stops when it hits the ui code to load the static store data. The preexisting project uses dynamically grabbed data from the database but this just needs a small list of options. (I miss the days of just using HTML). Firebug shows a non-helpful error in ext-all.js that q is undefined, but since that's obfuscated well maintained code I'm sure it's a problem in my code. Do I need to define the proxy for this even if it's static data? Thank you ahead of time!
Here is the model, store, and ui code
//model
Ext.define('HITS.model.ComboBox', {
extend: 'Ext.data.Model',
fields: [
{type: 'string', name: 'label', mapping: 'label'},
{type: 'string', name: 'value', mapping: 'value'}
]
});
//store
Ext.define('HITS.store.ReportType', {
extend: 'Ext.data.Store',
model: 'HITS.model.ComboBox',
storeId:'ReportType',
data: [
{label:'All Tags', value: 'AllTags'},
{label:'Key Findings', value: 'KeyFindings'}
]
});
//ui
<ui:ComboBox
renderTo="ui_report_list"
fieldLabel="Report:"
inputId="reportSelect"
store="ReportType">
The solution had a couple of changes required. The first was the "value" column, which is of course a reserved word in the database(oracle). The other was because I didn't add some prefunction comments for the model that trigger autogenerated code(I hate this practice).
The code here should mostly work but you'd need the model I ended up using. If you check sencha and don't use reserved words you should be ok.

dojo1.10 Dynamic update of dijit.form.Select

I was trying to asynchronously update a Select field via Memory and ObjectStore. This doesn't work. Setting the data to the Memory object before creating the Select element works fine. Updating the Memory object after creating the Select element doesn't work anymore.
Example code:
require([
"dojo/ready",
"dijit/form/Select",
"dojo/store/Memory",
"dojo/store/Observable",
"dojo/data/ObjectStore",
'dojo/domReady!'
], function(ready, Select, Memory, Observable, ObjectStore, dom){
ready(function() {
var mymem = new Memory();
var myobs = new Observable(mymem);
var mystore = new ObjectStore({ objectStore: myobs });
/* updating memory here works :) */
//mymem.setData([ { id: 2, label: 'qwertz2' }, { id: 3, label: 'qwertz3' } ]);
var s = new Select({
store: mystore
}, 'appsAdminQueueContainer');
s.startup();
/* updating memory here doesn't work :( */
mymem.setData([ { id: 2, label: 'qwertz2' }, { id: 3, label: 'qwertz3' } ]);
});
}
);
Real working example: https://jsfiddle.net/mirQ/ra0dqb63/5/
Is this a bug or is there a solution to be able to update the content of the Select field after creating it - without having to access the Select field directly?
UPDATE
Thank you for your response.
The use of dojo/ready was just a missed leftover while simplifying my code, sorry.
That the use of the ObjectStore is not necessary was not clear to me. Thanks for clearing up.
Okay, the real problem seems to be indeed the last point. I think I have to extend my description.
Updated/extended problem description:
I'm using a grid. At first I was using dojox/grid/DataGrid, but then I switched to dgrid. Everything works well, but I want to use dijit.form.Select as editor for one column. This works also well if the data is static. But in one column I have to read dynamic data from the server. This data comes in JSON format.
First I tried to solve this with the use of dojo/data/ItemFileReadStore - that worked. But it's deprecated and I need to implement a formatter for that column that has to have access to the same JSON data read from the server. I don't have the code for that solution anymore, but it didn't work. I wasn't able to successfully query the data from within the formatter function.
Then I switched to Memory and xhr. The response from the server comes after the Memory object is created (and, as it seems, after creating the Select), so I had to use setData to bring my loaded data in the store. And because the Select is only an editor of a grid, I don't have access to the object itself to be able to re-set the store after updating the data.
I hope my extended description makes my real problem a bit clearer. Thanks in advance for your help!
Mirko
This works for me:
require([
'dijit/form/Select',
'dojo/store/Memory',
'dojo/store/Observable',
], function (Select, Memory, Observable) {
var mymem = new Memory({
data: [{
id: 2,
label: 'qwertz2'
}, {
id: 3,
label: 'qwertz3'
}]
});
var myobs = new Observable(mymem);
var s = new Select({
labelAttr: 'label',
store: myobs
}, 'appsAdminQueueContainer');
s.startup();
myobs.add({ id: 4, label: 'qwerty' });
});
Notable changes:
There's no reason to use dojo/ready in this code. The require callback already waits for modules to load, and as long as this script is at the bottom of the body, there's no need to wait for the DOM to load, either.
There's no need to use a dojo/data store adapter. dijit/form/Select supports dojo/store as well (as of 1.8 if I recall correctly). This might also have been why observation wasn't working. The only difference is labelAttr must be specified on the Select since dojo/store has no concept of a label property.
(Edit) now that I re-read the question, I notice you are calling setData. setData does not fire observers. setData completely resets the store's data, and to reflect that, you would need to actually reset the store on the select entirely (which requires calling setStore, not set('store', ...), if you are using 1.9 or earlier, because Select was never updated properly to support the set API until 1.10).
(Edit #2) Given that the primary reason you are calling setData is due to creating the store before actually having data for it, your case would probably be greatly simplified by using the RequestMemory store implementation from dojo-smore. It basically re-adds the url support that dojo/data/ItemFileReadStore had but dojo/store/Memory didn't.

Displaying Only Certain Columns/Properties with Keen DataViz

I'm wondering how to display only certain columns on my table when I'm trying to do data visualization. Right now, every time that I do a table, it shows every single property or column. I tried to figure out how to only show certain columns properties by guessing based on the documentation for extraction within the keen.io docs (I've commented out my wrong guess)
var foo = new Keen.Query("extraction", {
eventCollection: "Purchases",
targetProperty: "zip",
// I've commented out line 7 because it doesn't work, it was just my guess on syntax...
// how do I only show certain columns of the table (columns are properties)
// vs. showing the entire table?
// propertyNames: ["zip","businessname"]
filters: [
{
"property_name" : "zip",
"operator" : "eq",
"property_value" : "80016"
},
{
"property_name" : "city",
"operator" : "eq",
"property_value" : "Aurora"
}]
});
client.draw(foo, document.getElementById("chart-09"), {
chartType: "table",
title: "Table"
});
https://gist.github.com/mrtannerjones/ba0cbd7340f2e016fcf2 - here is a link to the above code except on github in case something isn't formatted correctly.
Sorry if this question seems terribly basic or simple, I'm still really new at learning how to code.
Found the fix with a little help from David in the Keen.io Google group. I actually was just missing a comma after the 'property names', but what's more interesting to me is that the data visualization works with both camel case and with underscore separators. property_names and propertyNames both seem to work.

Creating and removing Ember Models dynamically / at runtime

I have been working on this for a couple of days now and have decided to bite the bullet and ask for help.
I am using ember-cli, and I'm trying to create Ember Models dynamically at runtime based on some metadata. An sample use case would be if a user wanted to specify a data set (query, file etc.); I would like to read the user's data file and setup a model based on the file's structure.
I have successfully setup an ember-cli application which uses Ember Data and Fixtures (for simplicity). My static example has three models and I can see the models and the data in the Store when I use the Chrome Ember debugger.
Now on to my dynamic example...
I have been able to successfully define a model at runtime by setting it up in IndexRoute
var IndexRoute = Ember.Route.extend({
init: function() {
// Create a simple model dynamically
var MyModel = DS.Model.extend({
defineAttributes: function(){
Ember.defineProperty(this, 'col1', DS.attr());
Ember.defineProperty(this, 'col2', DS.attr());
Ember.defineProperty(this, 'col3', DS.attr());
}.on('init')
});
// insert some data into our model
MyModel.reopenClass({
FIXTURES: [
{
id: '1',
col1: "key1",
col2: "value1",
col3: "value2"
},
{
id: '2',
col1: "key2",
col2: "value1",
col3: "value2"
},
{
id: '3',
col1: "key3",
col2: "value1",
col3: "value2"
}
]
});
}
});
The problem is that I don't see where the model has been placed, and it doesn't appear in the Chrome debugger in the Data (store).
If I change the definition of MyModel to Ember.Application.MyModel then I can see the Model is defined under Ember.Application in the console but it still isn't visible to the Ember Debugger.
I then tried to extend the above example to add the model hook as follows:
var IndexRoute = Ember.Route.extend({
init: function() {
...
},
model: function() {
return this.store.findAll('my-model');
}
});
But the call to this.store.findAll('my-model') fails in both cases. I am assuming that I am not wiring things up correctly.
In my example I am also aware that the name of my Model is not dynamic either so I really want to know how to create a name for my model programmatically at runtime.
I would really appreciate some help or guidance from those out there who are more experienced with the framework because I've been really impressed with Ember and the whole configuration over convention approach.
Thanks,
Dave
You're essentially defining something, then throwing it away. You'll need to attach it to your app's namespace (you can see it in your index file or configuration file if you're using Ember-cli).
Additionally, I doubt defining attributes on init will work, it might, but it isn't actually necessary.
Thirdly, do you really want to use Ember Data for this? Ember Data is very opinionated, and it sounds like you don't want to define things.