I'm trying to modify the stocklist Dynagrid demo which is designed to work with HTML5 and Javascript, it's originally designed to subscribe an item per subscription.
In my case, I have connected this demo to my lightstreamer server, the adapter in my server deals with itemgroub and fieldschema instead of itemList and fieldList which was used in the example.
I modified the code to subscribe using this item group and equivalent field schema, now the dynagrid listener (onVisualUpdate function) is capable to detect how many items in the item group and based on that it creates the equivalent number of rows, however, when I call getChangedFieldValue for and one of the fields in the dynagrid, I get null always, and based of that no data is updated on the screen.
What is the solution for this problem, and how can I get the updated values?
(Note: Currently, I get the data directly from the info paramter which is passed to onVisualUpdate function).
When using a Field Schema, fields in the subscription are identified by their 1-based index within the schema and not by their name. So, wen you call getChangedFieldValue try to use the 1-based index to identify a field.
Related
I have a recursive data structure to be fetched and displayed. I have a graph ql type as follow:
human {
name,
children: [human]
}
Now I wanted to incrementally fetch data and hence used to react classes HumanList and HumanItem, where I've used relay to fetch children only when a item is clicked. In my actual code relay gives children a null on very click i.e. on rendering very first set of children. I tried test code on relay playground and found similar issue. Here is the link to gist. Playground.js contains the code part and Playground.gql.js contains schema part. Clicking on each number open children under it. After 3 or 4 level it starts showing Found children as null. For me it happens on 1.1.2.2. If it doesn't happens so for you then try adding more levels in SCHEMA code and the bug would pop in.
I've already checked relay issues #246 and #536 but none of them helped.
Any help is very much welcome.
This was a bug. Given a plural field, when the time came to make a query for new data, we would diff what we have in the store with what the application wants. The bug was that we would assume that all records of a plural field have the same shape in the store, and only use the first store record in any plural field against which to diff. This was of course not true in your case, where some records in a plural field might be expanded and some might be collapsed.
This has been fixed as part of https://github.com/facebook/relay/issues/1243 and will be released in the version after Relay 0.9.1.
Working with React.js is really enjoyable.
I built a simple comment app based on the official tutorial.
You can add, edit, and delete comments. They are pulled via GET every 10 seconds.
At one point, the tutorial mentions optimistic updates: updating the UI before the server has responded in the case of a create, update or delete operation.
Since comments are part of a list, React suggests to assign a unique key to each comment.
I therefore use the database id of each comment as a key. That works fine for update and delete operations.
However, in the case of a create operation, I do not know the database id of a comment until it has been actually created server-side, and therefore I don't know what value to assign to the key.
At that point in time, the comment is added to the comment list but has no key/ID and therefore cannot be edited or deleted, until the list gets updated during the next API poll.
Can I work around that?
If you need the key to remain the same across updates, one option is to assign a temporary id to to an unused property. Then, use a function to retrieve the correct key for your list item models. As long as you account for the tempId property when updating the item, you can keep the key the same as long as the list remains in memory.
While you may not always care if the optimistic item gets removed and re-added, it can simplify your CSS when using on-enter or on-leave animations in your list. This also helps when you have stateful list item components.
Example:
let tempIds = 1; // 1 and up are truthy
// where ever you add the new item to your list
const newList = [...list, {...newItem, tempId: tempIds++}];
// get the right id
function getKey(instance) {
if (instance.tempId) {
return instance.tempId;
} else {
return instance.id;
}
}
// in your list render function
<List>
{list.map(model => (
<Item
key={getKey(model)}
//other props go here
/>
))}
</List
You need keys that are unique, consistent, and available. Your database IDs can't provide the third requirement, but you can--using local "client IDs". Obviously, you're responsible for guaranteeing their uniqueness and consistency.
You can add, edit, and delete comments. They are pulled via GET every 10 seconds.
We always POST to a resource which in returns yields the JSON response containing data we need, in your case ID. The delay is up to ~100ms which is fine.
If you set a temporary ID which is not equal to the one database is going to provide then React will re-render again once it receives the new data, just you will see two identical items as key is not the same.
I want to query object from Parse DB through javascript, that has only 1 of some specific relation object. How can this criteria be achieved?
So I tried something like this, the equalTo() acts as a "contains" and it's not what I'm looking for, my code so far, which doesn't work:
var query = new Parse.Query("Item");
query.equalTo("relatedItems", someItem);
query.lessThan("relatedItems", 2);
It seems Parse do not provide a easy way to do this.
Without any other fields, if you know all the items then you could do the following:
var innerQuery = new Parse.Query('Item');
innerQuery.containedIn('relatedItems', [all items except someItem]);
var query = new Parse.Query('Item');
query.equalTo('relatedItems', someItem);
query.doesNotMatchKeyInQuery('objectId', 'objectId', innerQuery);
...
Otherwise, you might need to get all records and do filtering.
Update
Because of the data type relation, there are no ways to include the relation content into the results, you need to do another query to get the relation content.
The workaround might add a itemCount column and keep it updated whenever the item relation is modified and do:
query.equalTo('relatedItems', someItem);
query.equalTo('itemCount', 1);
There are a couple of ways you could do this.
I'm working on a project now where I have cells composed of users.
I currently have an afterSave trigger that does this:
const count = await cell.relation("members").query().count();
cell.put("memberCount",count);
This works pretty well.
There are other ways that I've considered in theory, but I've not used
them yet.
The right way would be to hack the ability to use select with dot
notation to grab a virtual field called relatedItems.length in the
query, but that would probably only work for me because I use PostGres
... mongo seems to be extremely limited in its ability to do this sort
of thing, which is why I would never make a database out of blobs of
json in the first place.
You could do a similar thing with an afterFind trigger. I'm experimenting with that now. I'm not sure if it will confuse
parse to get an attribute back which does not exist in its schema, but
I'll find out, by the end of today. I have found that if I jam an artificial attribute into the objects in the trigger, they are returned
along with the other data. What I'm not sure about is whether Parse will decide that the object is dirty, or, worse, decide that I'm creating a new attribute and store it to the database ... which could be filtered out with a beforeSave trigger, but not until after the data had all been sent to the cloud.
There is also a place where i had to do several queries from several
tables, and would have ended up with a lot of redundant data. So I wrote a cloud function which did the queries, and then returned a couple of lists of objects, and a few lists of objectId strings which
served as indexes. This worked pretty well for me. And tracking the
last load time and sending it back when I needed up update my data allowed me to limit myself to objects which had changed since my last query.
I extended an Ext.data.Store (i.e users with model user) but when I iterate over custom JSON response and add each record, it replaces the first record and so the store consist of just one record instead of many
Here is my code (in image format) notice in line 215 i added a model on store on each iteration:
And here is the console output w/c only shows 1 on getCount():
I tried many solutions, and that includes changing the 'id' attribute to something else and also differ my user model to users model
But I have another store that is adding fine without problems.
EDIT: I tried adding it through javascript console and still it replaces the record 1:
The store's add function will automatically handle creation of the model(s). Your callback should be as simple as this:
callback: function(optionsusers, successusers, responseusers) {
loadingLoginModal.hide();
var responseusersJSON = Ext.JSON.decode(responseusers.responseText);
userStore.add(responseusersJSON);
loadingLoginModal.destroy();
that.showHomeView();
}
I've been trying to figure this out for quite some time now. I couldn't find anything that addresses this problem, but please correct me if I'm wrong.
The problem:
I have data from a JSON API comming in, with an nested array/object structure. I use mapping to initially fill the model with my data. To update this, I want to extend the model if new data arrives, or update the existing data.
As far as I found out, the mapping option key, should do this trick for me, but I might have misunderstood the functionality of the mapping options.
I've boiled down the problem to be represented by this example:
var userMapping = {
key: function(item) {
return ko.utils.unwrapObservable(item.id);
}
};
// JSON call replaced with values
var viewModel = {
users: ko.mapping.fromJS([], userMapping)
};
// Should insert new - new ID?
ko.mapping.fromJS([{"id":1,"name":"Foo"}, {"id":2,"name":"Bar"}], userMapping, viewModel.users);
// Should only update ID#1 - same ID?
ko.mapping.fromJS([{"id":1,"name":"Bat"}], userMapping, viewModel.users);
// Should insert new - New ID?
ko.mapping.fromJS([{"id":3,"name":"New"}, {"id":4,"name":"New"}], userMapping, viewModel.users);
ko.applyBindings(viewModel);
Fiddle: http://jsfiddle.net/mikaelbr/gDjA7/
As you can see, the first line inserts the data. All good. But when I try to update, it replaces the content. The same for the third mapping; it replaces the content, instead of extening it.
Am I using it wrong? Should I try to extend the content "manually" before using mapping?
Edit Solution:
I solved this case by having a second helper array storing all current models. On new data i extended this array, and updated the view model to contain the accumulated items.
On update (In my case a WebSocket message), I looped through the models, changed the contents of the item in question, and used method valueHasMutated() to give notice of changed value to the Knockout lib.
From looking at your example code the mapping plugin is behaving exactly as I would expect it to. When you call fromJS on a collection you are effectively telling the mapping plugin this is the new contents of that collection. For example:
On the second line, How could it know whether you were updating or whether you had simply removed id:2?
I can't find any mention of a suitable method that treats the data as simply an update, although you could add one. Mapped arrays come with some helpful methods such as mappedIndexOf to help you find particular items. If you receive an update data set simply loop through it, find the item and update it with a mapping.fromJS call to that particular item. This can easily be generalized into reusable method.
You can use ko.mapping.updateFromJS() to update existing values. However, it does not add new values so that would be a problem in your instance. Take a look at the link below for more details.
Using updateFromJS is replacing values when it should be adding them
Yes, you should first collect all data into a list or array and then apply the mapping to that list. Otherwise you are going to overwrite the values in your viewModel.