Dojo DataChart and manual ItemFileWriteStore update - websocket

I've decided to give Dojo a shot instead of using JQuery for once, and am having trouble manipulating a data store. I've got a DataChart bound to the contents of an ItemFileWriteStore i've populated by hand from a web socket JSON message:
fakeData = {
"identifier": "name",
"label": "Some data i'd like to add to later",
"items": [
{
"name": "appendToMe",
"values": [0.0, 1.0, 2.0, 3.0, 2.0, 1.0, 0.0]
}
]
};
store = new dojo.data.ItemFileWriteStore({
data: fakeData
});
var chart = new dojox.charting.DataChart("chartDiv", {});
chart.setStore(store, {"name":"*"}, "values");
At this point, the graph is displaying the "appendToMe" series i've created. Next, I receive another message, containing some new numeric value for the "appendToMe" values list.
How do I add it to the store, and will this be sufficient to trigger the graph to update?
I've looked at the [](write API) 'store.setValue', but it looks like I can only use this to replace the whole values chunk as one unit. In addition, I don't have a 'item' handle to use with the call, which appears to only be available if you use the newItem API instead of constructing the store with JSON.
Cheers!
Scott

First you need to fetch the appendToMe item.
store.fetchItemByIdentity({identity : 'appendToMe',
onItem : function (item) {
var itemValues = store.getValues(item, 'values');
itemValues.push(someNewValue);
store.setValues(item, 'values', itemValues);
}});
Then in the onItem, get your values, modify them, and then set them again using store.setValue()
As noted, getValues needs to be used to return the array of values instead of the usual getValue, which never returns an array. And similar with setValues.
http://dojotoolkit.org/api/1.6/dojo/data/api/Read
This getValues() method works just
like the getValue() method, but
getValues() always returns an array
rather than a single attribute value.
The array may be empty, may contain a
single attribute value, or may contain
many attribute values. If the item
does not have a value for the given
attribute, then getValues() will
return an empty array: []. (So, if
store.hasAttribute(item, attribute)
has a return of false, then
store.getValues(item, attribute) will
return [].)
setValues()
http://dojotoolkit.org/api/1.6/dojo/data/api/Write
Adds each value in the values array
as a value of the given attribute on
the given item. Replaces any previous
value or values. Calling
store.setValues(x, y, []) (with
values as an empty array) has the same effect as calling
store.unsetAttribute(x, y).

Related

Laravel | groupBy returning as object

I am trying to use a Laravel collection to return a groupBy as an array. However, it always seems to be returned as an object no matter what. I have tried to do $posts->groupBy('category')->toArray() but this seems to still return as an object. I have also tried $posts->groupBy('category')->all() and still it is returning as an object.
I don't know if this is something to do with Laravel returning methods within the routes, but I need this to return as an array.
Here is the code:
public function getFeatures($id)
{
return Feature::query()->get()->groupBy('category')->toArray();
}
The actual code is working fine and I'm getting results back but it just doesn't seem to be converting to an array. Thanks.
When doing a query to get (possibly) several items using Eloquent, Laravel will always return an instance of the Collection class that contains all the model objects. If you need them converted to array to use them in a view you could compact the elements. compact will make an associative array of the elements of the collection:
public function getFeatures($id)
{
$features = Feature::all();
return view('my_cool_view', compact($features));
}
On the other hand, if you need them converted to array to return them through an API, Laravel convert the response to JSON by default:
public function getFeatures($id)
{
return Feature::all();
}
Now, if you somehow need the collection converted to an array, just use toArray() like you indicated:
public function getFeatures($id)
{
$collection_of_features = Feature::all();
$array_of_features = $collection_of_features->toArray();
// use it for wherever you want.
}
By reading your comment on other answer, I realized what you mean.
Hi #HCK, thanks for the answer. The ->toArray() method doesn't seem to work and still returns it like { "category_1": [], "category_2": [] } whereas I need it to do ["category_1": [], "category_2": []]
First, this answer is based on a guess that you are doing something like this on your controller (you didn't posted the controller code):
return reponse()->json($theResponseFromGetFeaturesMethod);
Since inside php the $theResponseFromGetFeaturesMethod variable contains an dictionary array (something like ["key"=>"value]), when you convert it to a JSON, you will notice that this "conversion" happens.
This happens because Javascript arrays (and JSON) doesn't support dictionary arrays. See this sample on javascript console:
> var a = [];
undefined
> a['key'] = "value"
"value"
> a
> key: "value"
length: 0
__proto__: Array(0)
Note that the a still have a length of zero, but it now have an key property.
This happens because almost everything on javascript is actually an object. So the array is a special kind of object that have push, pop and many other array methods. Doing array[] = 'somevalue' is actually a shortcut to array.push('somevalue').
So, the behavior that you are observing is right, the toArray() method work as expected, and the JSON conversion too.
Another weird behavior is when you try to convert this PHP array to an JSON:
[
0 => 'a'
1 => 'b'
9 => 'c'
]
You will note that in this case, PHP will convert this array to an object too. The result in JSON will be:
{
"0": "a",
"1": "b",
"2": "c"
}
This is also the expected behavior, since the JSON syntax doesn't support defining the index for a value.

How to update item conditionally with branch in RethinkDB

I am trying to do simple upsert to the array field based on branch condition. However branch does not accept a reql expression as argument and I get error Expected type SELECTION but found DATUM.
This is probably some obvious thing I've missed, however I can't find any working example anywhere.
Sample source:
var userId = 'userId';
var itemId = 'itemId';
r.db('db').table('items').get(itemId).do(function(item) {
return item('elements').default([]).contains(function (element) {
return element('userId').eq(userId);
}).branch(
r.expr("Element already exist"),
//Error: Expected type SELECTION but found DATUM
item.update({
elements: item('elements').default([]).append({
userId: 'userId'
})
})
)
})
The problem here is that item is a datum, not a selection. This happens because you used r.do. The variable doesn't retain information about where the object originally came from.
A solution that might seem to work would be to write a new r.db('db').table('items').get(itemId) expression. The problem with that option is the behavior isn't atomic -- two different queries might append the same element to the 'elements' array. Instead you should write your query in the form r.db('db').table('items').get(itemId).update(function(item) { return <something>;) so that the update gets applied atomically.

how to correctly render referenced entities in list when I have objects instead of numberic ids?

right now in order for the list to render properly I need to have this kind of data passed in:
row = {
id: value,
name: value,
height: value,
categories: [1,2,3,4]
}
how can I adapt the code so that a list works with this kind of data?
row = {
id: value,
name: value,
height: value,
categories: [{id: "1"},{id: "2"},{id: "3"},{id: "4"}]
}
when I try to do that it seems that it applies JSON.stringify to the objects so it is trying to find category with id [Object object]
I would to avoid a per case conversion of data as I do now..
it seems that I cannot do anything in my restClient since the stringify was already applied
I have the same issue when I fetch just one data row e.g in Edit or Create.. categories ReferenceArrayInput is not populated when categories contains objects
Have you tried using format?
https://marmelab.com/admin-on-rest/Inputs.html#transforming-input-value-tofrom-record
Might help transform your input value. Then you can use format() to change values back to the format your API expects.
If this does not work then you will have to probably create a custom component out of ReferenceArrayInput.

Ember - How to sort by transform?

I am trying to sort a model in Ember by a field that has a transform. The original field is an IntegerField (served by an API), which is ordered appropriately. When the field is deserialized by the transform into the string representation, ember sorts by the string, as opposed to the original order.
For instance, if this is the deserialization:
{
10: 'Built',
20: 'Started',
30: 'Finished',
};
I want this to appear as Built, Started, Finished when sorted, according to the original enum. However, it will actually be sorted as Built, Finished, Started, per the alphabetized strings.
Is this possible when using Ember.computed.sort?
i know it is not what you want, but after many search i just do this type of sort on the ember
var sortArray = Ember.ArrayProxy.extend(Ember.SortableMixin).create();
sortArray.set("content", []);
sortArray.addObject({"id":10 , "name": 'Built'});
sortArray.addObject({"id":20 , "name": 'Started'});
sortArray.addObject({"id":30 , "name": 'Finished'});
sortArray.set('sortProperties', ["id"]).set("sortAscending", true);

Flyweight VirtualRepeater containing IntegerPicker

In my Enyo app, I have a VirtualRepeater which produces Controls containing various text displays and an IntegerPicker.
I have two problems with this repeater:
1) If three rows are produced, clicking on the IntegerPicker in rows 1 and 2 brings up the drop-down picker UI over the top of the IntegerPicker in row 0.
2) I initialise each IntegerPicker with a max value using setMax(). However, if three rows are produced, the IntegerPickers in rows 0 and 1 will have the same max value as that in row 2.
It looks as if only one IntegerPicker is being created and is being used on the first row.
I tried replacing my VirtualRepeater with a Repeater, and changed my repeater row creation function to return a new instance of the item containing the IntegerPicker, instead of returning true. However this produces the error:
warning: enyo.Component.addComponent(): Duplicate component name "itemName" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.
It seems that Repeaters need their delegates created inline, which seems quite inelegant.
This code sample illustrates the problem:
enyo.kind({
name:"Test",
kind:enyo.Control,
components: [
{
kind: "VirtualRepeater",
onSetupRow: "setupRow",
components: [{
name: "theIP", kind: "IntegerPicker", min:0
}]
}
],
setupRow: function(inSender, inIndex) {
if (inIndex < 3) {
this.$.theIP.setMax(inIndex);
return true;
}
return false;
}
});
How can I create an arbitrary number of IntegerPickers in my app? Any help appreciated!
What you are doing with theIP in your setupRow function is accessing a specific IntegerPicker itself, which is a child component of the Virtual Repeater. To set the max value of a given IntegerPicker corresponding to the row, give your VirtualRepeater a name attribute, like "PickerList":
kind: "VirtualRepeater",
onSetupRow: "setupRow",
name: "PickerList",
components:[//this should be empty to begin with]
Then you can access each row in the repeater like this:
setupRow: function(inSender, pickerMax) {
var newPicker = new IntegerPicker(pickerMax);
this.$.PickerList.push(newPicker);
To get a specific row in the VirtualRepeater you need to do it like this:
this.$.PickerList[1];
Here is an extended Enyo tutorial which makes use of the VirtualRepeater:
https://developer.palm.com/content/resources/develop/extended_enyo_tutorial.html

Resources