Admin on rest : How to Edit a JSON Array field of Key Value Pairs - admin-on-rest

I have a data structure in the REST end point like this :
[
{k:"1", v:"ABC"},
{k:"2", v:"XYZ"},
]
How to Display such data in Edit Form such that I can remove and Add New ? If I use SelectArrayInput, then it complains of :
Invariant Violation: Objects are not valid as a React child (found: object with keys {k, v}). If you meant to render a collection of children, use an array instead.
Can someone please help on what is the best possible way ?

Related

SOLVED: Looking for a smarter way to sync and order entries in Laravel/Eloquent pivot table

In my Laravel 5.1 app, I have classes Page (models a webpage) and Media (models an image). A Page contains a collection of Media objects and this relationship is maintained in a "media_page" pivot table. The pivot table has columns for page_id, media_id and sort_order.
A utility form on the site allows an Admin to manually associate one or more Media items to a Page and specify the order in which the Media items render in the view. When the form submits, the Controller receives a sorted list of media ids. The association is saved in the Controller store() and update() methods as follows:
[STORE] $page->media()->attach($mediaIds);
[UPDATE] $page->media()->sync($mediaIds);
This works fine but doesn't allow me to save the sort_order specified in the mediaIds request param. As such, Media items are always returned to the view in the order in which they appear in the database, regardless of how the Admin manually ordered them. I know how to attach extra data for the pivot table when saving a single record, but don't know how to do this (or if it's even possible) when passing an array to attach() or sync(), as shown above.
The only ways I can see to do it are:
loop over the array, calling attach() once for each entry and passing along the current counter index as sort_order.
first detach() all associations and then pass mediaIds array to attach() or sync(). A side benefit would be that it eliminates the need for a sort_order column at all.
I'm hoping there is an easier solution that requires fewer trips to the database. Or am I just overthinking it and, in reality, doing the loop myself is really no different than letting Laravel do it further down the line when it receives the array?
[SOLUTION] I got it working by reshaping the array as follows. It explodes the comma-delimited 'mediaIds' request param and loops over the resulting array, assigning each media id as the key in the $mediaIds array, setting the sort_order value equal to the key's position within the array.
$rawMediaIds = explode(',', request('mediaIds'));
foreach($rawMediaIds as $mediaId) {
$mediaIds[$mediaId] = ['sort_order' => array_search($mediaId, $rawMediaIds)];
}
And then sorted by sort_order when retrieving the Page's associated media:
public function media() {
return $this->belongsToMany(Media::class)->orderBy('sort_order', 'asc');
}
You can add data to the pivot table while attaching or syncing, like so:
$mediaIds = [
1 => ['sort_order' => 'order_for_1'],
3 => ['sort_order' => 'order_for_3']
];
//[STORE]
$page->media()->attach($mediaIds;
//[UPDATE]
$page->media()->sync($mediaIds);

Using Spring MongoTemplate to update nested arrays in MongoDB

Can anyone help with a MongoTemplate question?
I have got a record structure which has nested arrays and I want to update a specific entry in a 2nd level array. I can find the appropriate entry easier enough by the Set path needs the indexes of both array entries & the '$' only refers to the leaf item. For example if I had an array of teams which contained an array of player I need to generate an update path like :
val query = Query(Criteria.where( "teams.players.playerId").`is`(playerId))
val update = Update()
with(update) {
set("teams.$.players.$.name", player.name)
This fails as the '$' can only be used once to refer to the index in the players array, I need a way to generate the equivalent '$' for the index in the teams array.
I am thinking that I need to use a separate Aggregate query using the something like this but I can't get it to work.
project().and(ArrayOperators.arrayOf( "markets").indexOf("")).`as`("index")
Any ideas for this Mongo newbie?
For others who is facing similar issue, One option is to use arrayFilters in UpdateOptions. But looks like mongotemplate in spring does not yet support the use of UpdateOptions directly. Hence, what can be done is:
Sample for document which contain object with arrays of arrayObj (which contain another arrays of arrayObj).
Bson filter = eq("arrayObj.arrayObj.id", "12345");
UpdateResult result = mongoTemplate.getDb().getCollection(collectionName)
.updateOne(filter,
new Document("$set", new Document("arrayObj.$[].arrayObj.$[x].someField"), "someValueToUpdate"),
new UpdateOptions().arrayFilters(
Arrays.asList(Filters.eq("x.id, "12345))
));

How to update nested redux state

I have the following structure
lookups --> Object
lookups.CATEGORIES --> array of category objects
lookups.TIMEZONES --> array of timezone objects
I would like to add new object, which is a lookup object which has lookup_type property. It could be either 'CATEGORY' or 'TIMEZONE'.
Depending on lookup_type, the newly added object has to be added either to CATEGORIES or TIMEZONES object. How this could be achieved?
The structure of lookups object
lookups: {CATEGORIES:[{obj1}, {obj2}...], TIMEZONES:[{obj1}, {obj2}, {obj3}...]}
You can use spread on the nested object or array too:
return {
...state,
[action.lookupType]: [
...state[action.lookupType],
action.value,
]
};
That would add a new item to Categories or Timezone, if you want to replace a value or insert it at an index etc then you should construct the new array how you want it just above the return and pass that instead. Also note that array spread is ES7.
You probably want to pass your lookup object as the payload of an action, which your lookup reducer handles. In the lookup reducer check for the value action.payload.lookup_type and return the state with a new CATEGORIES or TIMEZONES array containing the old values of that array with the lookup object insterted. You should probably check out some redux examples first, if you are unsure how to work with it.

Index JSON Array in Postgres DB

I have a table where each row has a JSON structure as follows that I'm trying to index in a postgresql database and was wondering what the best way to do it is:
{
"name" : "Mr. Jones",
"wish_list": [
{"present_name": "Counting Crows",
"present_link": "www.amazon.com"},
{ "present_name": "Justin Bieber",
"present_link": "www.amazon.com"},
]
}
I'd like to put an index on each present_name within the wish_list array. The goal here is that I'd like to be able to find each row where the person wants a particular gift through an index.
I've been reading on how to create an index on a JSON which makes sense. The problem I'm having is creating an index on each element of an array within a JSON object.
The best guess I have is using something like the json_array_elements function and creating an index on each item returned through that.
Thanks for a push in the right direction!
Please check JSONB Indexing section in Postgres documentation.
For your case index config may be the following:
CREATE INDEX idx_gin_wishlist ON your_table USING gin ((jsonb_column -> 'wish_list'));
It will store copies of every key and value inside wish_list, but you should be careful with a query which hits the index. You should use #> operator:
SELECT jsonb_column->'wish_list'
FROM your_table WHERE jsonb_column->'wish_list' #> '[{"present_link": "www.amazon.com", "present_name": "Counting Crows"}]';
Strongly suggested to check existing nswers:
How to query for array elements inside JSON type
Index for finding an element in a JSON array

Output entities with relationships in json

I have a device entity which has one-to-many relationship with picture entity. Like one device has many pictures. How can I output in JSON all device properties plus array of pictures?
When I try:
dd(Device::find(1)->pictures);
I get array of laravel objects with some additional information. I tried to do it in some ways but didn't managed to get just an array of simple picture objects (or array of arrays)
Although this works:
foreach (Device::find(1)->pictures as $picture) {
$data['pictures']['path'] = $picture->path;
}
dd($data['pictures']);
It seems weird to form array that way
Basically I need to output json with arrays of one-to-many objects, like pictures and some other. So I'll get something like:
["name": "myDevice", "price": "15", "pictures": [...], "another": [...]]
I am using laravel 3
Are you using Laravel 3? In that case this should do the trick:
return Response::eloquent(Device::with('pictures')->find(1));
If your are using Response::eloquent the content-type is also automatically set to application/json.
Edit: if you want only certain fields to return, you could use Response::json(Device::with('pictures')->lists('name', 'id')); to return an array just of that values already JSONified.

Resources