I'm using tree with dijit.tree.ForestStoreModel as a model and JsonRestStore as a store.
It works fine when tree is initialised. After that I want to add another item to the store manually (not from server) to update the tree.
My question is how can I do it without posting the item to server by rest, just to local storage. I used store.newItem() but without success.
I think in this situation, you probably wouldn't want to actually use a JsonRestStore. Depending on your use case, you may want to use some other type of dojo store like Memory and on initialization of your Tree, load the data from your server through some other method.
Finally I was able to figure out what fired requests to server. That was jsonRestStore.save(), that commits dirty data to server.
After I've removed it from my code, I use the following to add new data to tree:
jsonRestStore.fetchItemByIdentity({
identity: parent.path,
onItem: function (parent) {
store_cloud.newItem(child, {
parent: parent,
attribute: 'children'
});
}
});
Here I have a child node and parent one. Also 'children' attribute is used for referencing.
Related
I'm new to ember-data. I'm trying to load comment list from a API using multiple API calls. The comment list feature works like below,
A comment object can have a parent comment or children comments (replies)
All comments (children & parent) from different comment threads are list down in a single comment list using a 1st API call.
If user click on specific comment from above list it will prompt respective comment thread. Respective parent or children comments loading using 2nd API call
The comment model is implemented as below,
export default CommentModel.extend( {
parent: computed(function() {
return get(this, 'store').queryRecord('comment', {
_overrideURL: `comments/${get(this, 'id')}/parent`,
});
}),
children: computed(function() {
return get(this, 'store').query('comment', {
_overrideURL: `comments/${get(this, 'id')}/children`,
});
}),
...
As this implementation, if user click on child comment (reply) from the comment list, the 2nd API call with load the respective parent comment and parent comment will load its children comments again. That behaviour cause reload the comment list component in UI.
Is there any other way in ember-data to lazy load relationship without creating already existing objects?
If you really need to go that road, you may try to perform a findRecord instead of a queryRecord and use adapterOptions to customize your model's adapter urlForFindRecord method.
TL;DR
Why you shouldn't:
IMHO, you have a data flow problem in your proposed design.
You shouldn't be performing async code inside a computed property (nor returning immutable object as queryRecord response).
Tasks work great for that purpose.
You shouldn't be having your model to load data (that should be route's responsibility), which violates both MVC and DDAU principles.
There is this great article from 2015 on that
As a matter of fact since ember octane, you shouldn't be using computed properties at all, they have been replaced by actual getters and tracked properties.
More on that
Ember is a great framework, good luck on your journey!
I have 1 main component. Inside of this component i use WebSockets to receive data from the server. I receive an object with a range of fields inside it. The number of fileds can be from 0 till 10, for example. Each time i receive an object i use forEach() to take all fields. For each field i need to init a component, like this:
self.dcl.loadIntoLocation(StreamComponent, self.elementRef, 'stream');
If a copy of a component for current field of an object already exists, i need to update it with new received data within the view. The main my problem is i don't know how to pass the data from WebSockets to created component. I can create and init it, but i never mind how to pass data to it. Any ideas ?
You could try to leverage the promise returned by the method:
self.dcl.loadIntoLocation(
StreamComponent, self.elementRef, 'stream').then((compRef:ComponentRef) => {
compRef.instance.someAttr = something;
});
This promise allows you to get the instance of the newly created component and set data in its properties (for example, the web socket).
I would like to have a polymer element with two sub-elements, one that produces data, and the other that performs some action when the data changes (in my case: sending a notification to a server).
To implement this, I wrote a polymer element, namely root, with the following structure (names changed to simplify the discussion):
<producer data={{foo.bar}}></producer>
<consumer data=[[foo]]></consumer>
The producer changes the data using the set('property', 'value') method, so that the root element sees the notifications. The problem is that the consumer element won't notice the changes to foo since they involve a sub-property.
To solve this, I tried using a computed binding as follows:
<producer data={{foo.bar}}></producer>
<consumer data=[[_compute(foo)]]></consumer>
...
_compute: function() {
return this.foo;
}
However this won't cause the consumer to be notified. I think the reason for this is that the returned object is the same reference (only a sub-attribute changed). Currently the workaround I've used is to use the following version of the compute function:
_compute: function() {
return Object.assign({}, this.foo);
}
This works (the consumer element gets notified), however I'm affraid it might not be the most efficient (I'm creating an object at every call of _compute) and/or elegant way. Then my question is: what is the proper way to achieve this behavior in Polymer?
Do you have access to modify the consumer element?
The best way to fix this is to have the consumer element have a multi-property observer that listens for sub-property changes on the data property.
It might look something like this:
Polymer({
is: 'consumer',
properties: {
data: Object
},
observers: ['consumeData(data, data.*)'],
consumeData: function (data) {
//Do whatever you were planning on doing with data here
}
});
The advantage of an approach like this is that your 'consumer' element just 'knows' how to consume the data object when a sub-property on it changes. Because of the lighter weight approach to data binding in Polymer, trying to implement this behavior outside of the 'consumer' element will necessarily be more expensive and more complicated, since it requires either tricking the data binding into thinking the data object is new by supplying it with a new reference to a copy or forgoing the data binding altogether and building an approach on top of events and calling methods on the consumer in response to events. So if at all possible, I would recommend trying the approach above.
Polymer's data binding does not work the same way as some other two-way enabled data binding implementations, like what you might find in AngularJS. Rather than using dirty-checking, which is extremely expensive, Polymer uses an event based 'path notification' approach. When a sub-property on a property changes, a Polymer element which has that property will fire an event to it's immediate children bound to that property, notifying them that the path 'property.subProperty' has changed. In order for consumer to act on those changes, it has to be told to listen to changes along that 'property.subProperty' path. We specify paths in our polymer observers by using the syntax above. In this case, putting data.* in our observer means we want to listen to any path off of data, so that any notified property change on the data property will trigger the observer.
As you have noticed there isn't an elegant way of doing this. The way you got it working is interesting.
An alternative way which I would expect to work would be to fire an event from within the producer element.
this.fire('data', {data: this.foo.bar});
and then have the parent/root element listen for this event and then update the data property of the consumer element.
<producer on-data="handleData"></producer>
<consumer id="consumer"></consumer>
handleData: function(e) {
self.$.consumer.data = e.detail.data;
}
Edit:
You could make a new property that you compute within the producer element. Then you won't have to do a computed function everytime you want to access foo.bar
Producer element
properties: {
foo: {},
bar: {
computed: 'computeBar(foo)'
}
}
Root element:
<produce bar="{{bar}}"></producer>
<consumer data="[[bar]]"></consumer>
First of all I know how to set a LoadingMask for a component but have a problem with the uncoupling of the system I am making so I am just looking for a hint/idea.
I am using a MVVC architecture and in the View I have a Container with several Components in it, one of which is a Grid.Panel. The grid is bound to a store and has an event that when fired calls a method of the store. The following code happens in the ViewController:
functionForEvent() {
var store = getStoreForThisGrid();
store.update(Ext.getBody());
}
What happens now is the update() method makes a request to a server, that updates the store itself and the view component, and I need the loading mask during that time. How I handle the situation right now is I pass Ext.getBody() (or a DOM Element representation of a specific component) to the method and it deals with that reference. This function part of the store that is attached to the Grid and resides in the Store:
update : function (el) {
el.mask();
makeRequest();
el.unmask();
}
What I am looking for is another way (Pattern maybe if such exists for JavaScript) to access the View component from the Store instead of passing it around because that does not seem like a good practice and couples the system.
Since I come from a Java background I would have used the Observer pattern but cannot find how to apply this in JS.
I want my app to fire a method (client side) when a particular subscribed data is changed? for example, the client side has this following subscription
Meteor.subscribe('thePlayers');
thePlayers subscription returns a collection of data which is being displayed in the html through the template.
so whenever the collection get changed, Meteor automatically change the data in the HTML also. Besides this feature, I want my app to fire a method say fire() to be executed as soon as data get changed. What should i do to achieve this?
As David Weldon correctly, cursor.observerChanges is the way to go. Here's how you can use it for your example (assuming your collection is called thePlayers):
client-side
methodCaller = function (methodName) {
return function (/* arguments */) {
Meteor.apply(methodName, arguments)
}
}
var fireCaller = methodCaller('fire')
thePlayers.find().observeChanges({
added: fireCaller,
changed: fireCaller,
removed: fireCaller
})
In case you need this fire() to be run on server, you don't need a method, you can just rely on the observeChanges feature or just observe in your publication. See this question to get an example of how you can achieve that.
In case you need this fire() to be run on client, keep in mind that every helper in your template is reactive, that means it will re-run each time your collection is changed. I assume that it requires that you use the subscription inside it, but that needs to be confirmed.