I have my normalized store with lists and id mappings:
{
"byId": {
"images": {
"10984": {"id": "10984", "src": "/img.png"}
}
},
"myImages": [
"10948"
]
}
Now I want to create a new image, and add it to the list. The problem is that I don't have an id for it until I send it to the server. So I could generate a random id
"tempid19048": {"id": "tempid19048", src: "/img.png"}
"myImages": [
"10948",
"tempid19048"
]
And then I save it to the server and get an id back I dispatch an action. I may have tempid19048 used in multiple parts of the state.
What's a sane way to update everything with the new id? Am I approaching this all wrong?
Because Redux is really a client-side state manager, generally you just want to mirror the global state and thats it. As you know, unlike Flux/GraphQL, there isn't any functionality for caching, optimistic updates etc. My gut tells me building this would be difficult without compromising the pure simplicity that Redux is built on.
That said, I found redux-optimistic that mimicks Flux's optimistic updates for Redux. I've not used it, but it looks nice enough.
But with even with that said, I'd still highlight the simple solution of designing-out any need for temp ids / optimistic updates etc:
make a request to create the image on the server
show a spinner
on success message from the server, add the new image with the new id to the global state
You can make IDs in "myImage" as key-value pair.
"myImages": {
"10948": "10948",
"tempid19048": "tempid19048"
}
Now where ever you want to use you can use as
myImages["tempid19048"]
This will give you its current value as "tempid19048".
And if you need to change this tempId you need to change only the value, and key remains same.
"myImages": {
"10948": "10948",
"tempid19048": "newServerID"
}
Hence, irrespective of number of places you are using tempID now you need to update in only one place.
Related
I have a doc in couchDB:
{
"id":"avc",
"type":"Property",
"username":"user1",
"password":"password1",
"server":"localhost"
}
I want to write a view that returns a map of all these fields.
The map should look like this: [{"username","user1"},{"password","password1"},{"server","localhost"}]
Here's pseudocode of what I want -
HashMap<String,String> getProperties()
{
HashMap<String,String> propMap;
if (doc.type == 'Property')
{
//read all fields in doc one by one
//get value and add field/value to the map
}
return propMap;
}
I am not sure how to do the portion that I have commented above. Please help.
Note: right now, I want to add username, password and server fields and their values in the map. However, I might keep adding more later on. I want to make sure what I do is extensible.
I considered writing a separate view function for each field. Ex: emit("username",doc.username).
But this may not be the best way to do this. Also needs updates every time I add a new field.
First of all, you have to know:
In CouchDB, you'll index documents inside a view with a key-value pair. So if you index the property username and server, you'll have the following view:
[
{"key": "user1", "value": null},
{"key": "localhost", "value": null}
]
Whenever you edit a view, it invalidates the index so Couch has to rebuild the index. If you were to add new fields to that view, that's something you have to take into account.
If you want to query multiple fields in the same query, all those fields must be in the same view. If it's not a requirement, then you could easily build an index for every field you want.
If you want to index multiple fields in the same view, you could do something like this:
// We define a map function as a function which take a single parameter: The document to index.
(doc) => {
// We iterate over a list of fields to index
["username", "password", "server"].forEach((key, value) => {
// If the document has the field to index, we index it.
if (doc.hasOwnProperty(key)) {
// map(key,value) is the function you call to index your document.
// You don't need to pass a value as you'll be able to get the macthing document by using include_docs=true
map(doc[key], null);
}
});
};
Also, note that Apache Lucene allows to make full-text search and might fit better your needs.
I have three tables, 'sessions', 'classes' and 'schedules' which they are connected each other.
sessions: id, name, descr
classes: id, session_id, name
schedules: class_id, session_id, date
A class belongs to a session, while the schedules is a N:M relations which gives the opportunity to have particular date for each session within a single class.
My problem comes when I have to display these information, I have a function which displays all Sessions:
$sessions = Session::all();
and I have another function which displays the date of a specific class and a specific session as below:
$result = Schedule:where('class_id','=',$classId)->where('session_id','=',$essionId)->first();
So let say I have 30 sessions for a single class, when it comes to my front-end app which is written in AngularJS I dont know how to handle the displaying here using the ng-repeat iterating thru all sessions and then make another call withing the ng-repeat iteration to call the schedule to display the date of the session, this is not a good practice I guess in AngularJS.
Could anyone tell me what would be the best option for me to handle this problem? Shall I have to modify the back-end? like edit the Session:all(); query to include also the Schedule table? or what is the best way?
I supposed you have already config your relations in models, if not look here
As for me, I use Fractal to customize display data. Also there is convenient method called Available includes
So you can request your data like /sessions/?include=classes and get output
{data: [{
session_id: 1,
some: "data",
classes:[{
class_id: 11,
some: "class_data"
}]
}]}
I would "eager load" the data, so you can access all the object's parents through the object you loaded. This way you can fill your table rows one by one by just iterating over 1 object.
There is excellent documentation about eager loading at the Laravel website, so I suggest you start there
I have created a table using handsontable:
hot = new Handsontable(container, {
data: [],
dataSchema: {id: null},
startRows: 5,
startCols: 1,
colHeaders: ["Car"],
columns: [
{data: 'id'}
],
rowHeaders: true,
minSpareRows: 1,
persistentState: true,
onChange: function (change, source) {
console.log(change);
console.log(source);
}
});
They have a pretty elaborate example on saving/loading to/from server using ajax. However, I just want use persistent state to save load all the stuff.
In particular I want when a cell's value in hot is changed I want to save this information in some local storage, so that I can retrieve it later. The closest I got was to use change parameter in onChange and save it manually to localStorage. My main question is how can I save cell's info once it changed to some local storage? Better to persistentStorage.
Also, can I save the whole hot table to local storage? What is more efficient to update the whole table every time, or to update just the value of that particular cell? Is there a quick way to load table? Can you provide a good example how can I save/load table to local storage on change?
Eventually, I went with something like this:
hot = new Handsontable(container, {
data: [],
dataSchema: {id: null},
startCols: 4,
colHeaders: ["ID"],
columns: [
{data: 'id'}
],
rowHeaders: true,
minSpareRows: 4,
afterChange: function (change, source) {
// restore table after reload of a page
if (source === "loadData") {
// load data from local storage
if (localStorage['data']) {
var data = JSON.parse(localStorage['data'])
this.loadData(data);
this.render();
return
}
}
else {
// save all data to local storge if the edit happends
localStorage['data'] = JSON.stringify(this.getData());
return
}
}
});
There are many ways of doing what you ask so you'll have to try it out and see. The most common way to do what you ask is to get the data onAfterChange. In this callback (read the documentation) you have access to the new value and the row and col indeces. At that point, you can do one of two things:
You can store in localStorage the (row,col) with the data at that position. That's the first option. Then onLoad you can go through all available key,value pairs and set the data array.
The second thing you can do is much easier but more costly. In the onAfterChange callback, every time, save the contents of hot.getData(). You can do it like this:
// assuming 'hot' is the name of your handsontable instance
localStorage["data"] = hot.getData()
Storing each cell is fast and takes minimal space on saving (so this part will be fast) but it's harder to implement the loading code. The storing of all the data might take longer but it makes your code much easier to implement (on load, simply set the data object to the value of localStorage.data).
I would try the storing of all the data first (on the largest data set you think you'll ever have) and seeing if it is slow. If it is, use the per-cell approach.
EDIT: persistent state taken from documentation
The following is the direct quotation. The difference here from what I posted earlier is that instead of doing localStorage["data"] = hot.getData() you would instead do hot.persistantStateSave("data", hot.getData())
How to save data locally.
You can save any sort of data in local storage in to preserve table state between page reloads. In order to enable data storage mechanism, persistantState option must be set to true (you can set it either during Handsontable initialization or using the updateSettings method). When persistentState is enabled it exposes 3 hooks:
persistentStateSave (key: String, value: Mixed) Saves value under given key in browser local storage.
persistentStateLoad (key: String, valuePlaceholder: Object)
Loads value, saved under given key, form browser local storage. The loaded value will be saved in valuePlaceholder.value (this is due to specific behaviour of PluginHooks.execute() method). If no value have been saved under key valuePlaceholder.value will be undefined.
persistentStateReset (key: String)
Clears the value saved under key. If no key is given, all values associated with table will be cleared.
I'm working on a basic year, make, model dependent drop down menu, but started working backwards. I'm currently working on making my success callback dependent on the model drop down selection. For instance, if I choose 2006, lexus, is250, I only want my success callback to display that vehicle.
Most of my code can be found http://codepen.io/cfavela/pen/bozie/ (make sure to collapse the CSS page to make it easier to read)
My results page (modelsTest.html) contains the following:
{
"Car": "2012 Chevrolet Avalanche",
"Price": "$10,999",
"Features": "Soft seats!"
"Img": "/css/img/2012_Avalanche.jpeg"
}
What I've tried to do is add another car using an array and $.each, but the problem with this result is that it returns every vehicle if I click on search. How can I make the success callback dependent on the model selected?
As I commented above, according to this SO How to read the post request parameters using javascript, you can not get post data at client side level, you would need a server side to do that.
So you could try using GET and form your query ($('#vehicle').val()) as part of query string, then base on the query string, do some javascript logic at modelsTest.html and return the json you want. (but I don't think this will work, because I don't think you can return pure json in a real html file, so guessing your modelsTest.html just contain json. but I could be wrong hence I leave this as a possible solution)
or do the filtering in the success: function() before append to the msg.
I've seen other posts in this site regarding the same issue and I've tried the solutions given. I've also visited the links that may offer a solution but I'm still stuck with the same error.
I'm using DOJO and something as simple as this won't even work
myStore.newItem({id: 'test', otherfield: 'otherinfohere'});
myStore.save();
Supposedly the "newItem() was not passed an identity for the new item" error appears when you haven't provided an identifier for the new item, which i have.
The whole purpose of this (Just in case anyone can provide a good idea or has done something similar before) is that i want to create a data grid that shows info from a particular store. The problem is, that in that store all the items may not have the same structure. For instance:
I may have a store that looks like this
{identifier: 'id',
label: 'name',
items: [
{ id:'1', name:'Ecuador', capital:'Quito' },
{ id:'2', name:'Egypt', capital:'Cairo' },
{ id:'3', name:'El Salvador', capital:'San Salvador' , additionalField: 'otherinfohere'},
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', additionalField: 'otherinfohere'},
]}
This is possible because I'm the one constructing the store in a Spring Controller (I'm also using the Spring Framework) from information I have locally stored in a Berkeley DB. So what i need is a data grid with a dynamic layout because I don't want blank spaces to show in the view in the rows with lesser amount of fields, and i need to show all the info in the store at the same time, but i don't know how to do this.
I thought of doing it by creating a simple layout of only 1 field. In it I would load data from a store i create dynamically at runtime. The data in the store would be composed of HTML combined with the values coming from the original store so I could obtain something like this, which is inside an attribute of a JavaScript Object and let the browser parse it for me:
<div><span>id: originalID </span>....</div>
This of course is a simple example, the html layout i'm looking for is far more complicated, but i think that passing it as a string to an object might do the trick.
The problem is that i don't even know if that idea will work because i get that error whenever i try to add values to my secondary store.
rdb.modules.monitor.historicStore.fetch({onComplete: function(items, request){
for (var i = 0; i < items.length; i++){
var item = items[i];
var obj = new Object();
obj.id = rdb.modules.monitor.historicStore.getValue(item, "id");;
var html = "<div><span>";
html += rdb.modules.monitor.historicStore.getValue(item, "sql");
html += "</span></div>";
obj.html = html;
myStore.store.newItem(obj);
}
}});
In this context "historicStore" refers to the JSON store that has the values that i need to convert and add to "myStore" after i added some HTML.
I hope you got the main idea of what I'm trying to do. If anyone can help me we either of these problems i would really appreciate it. Thanks in advance
For the issue regarding store:-
"id" is mandatory for a store, if it is going to be used for a grid(datagrid, EnhancedGrid, etc. whatever). The items are handled only on basis of "id" attribute by the grid data structures.
Usually, id can be a loop variable/ auto incrementation, to avoid any cases like you have said. Before adding the store to the grid, ensure that all items have the id attribute. You can write a function which will loop through each item and check for this, else add an auto-incrementing value for the id attribute of that item.