Dojo dGrid/dStore realtime update - javascript

I've been trying to get my dgrid/dstore grid in realtime.
As var as I understand the function 'Observable' is deprecated, and also it doesnt work for me.
I've tried to update the grid via a Interval timer but then the whole grid is erased and new loaded. How to update the whole grid 'inline' without erasing, and showing 'loading data'?
This is my basic code:
var timer = setInterval(function() {
store.invalidate(); // Invalidate the cache
store.fetch(); // Perform a new request for all items
grid.refresh();
}, 500);

Observable does not exist in dstore, but there is a Trackable mixin which can be used instead. As for updating the grid when new content is fetch from the store, you could use a dstore/Cache and then pass the cached Memory store that mixes in Trackable to the grid to use instead. Each time new data is added to the caching store, it will also be reflected in the grid.
require([
'dgrid/OnDemandGrid',
'dstore/Rest',
'dstore/Memory',
'dstore/Trackable',
'dstore/Cache',
'dojo/domReady!'
], function (OnDemandGrid, Rest, Memory, Trackable, Cache) {
var restStore = new Rest({
target: '/mockRequest/'
});
var store = Cache.create(restStore, {
cachingStore: new (Memory.createSubclass(Trackable))()
});
var grid = new OnDemandGrid({
collection: store.cachingStore,
columns: {
id: 'ID',
name: 'Name',
description: 'Description'
},
loadingMessage: 'Loading...'
}, 'main');
grid.startup();
setInterval(function () {
store.fetch();
}, 2000);
});

Related

How to process two sets from different models in one custom control

Aim:
I'd like to have two models(sets of data) passed to the custom control with a predefined search field, in which later on I can execute filtering.
I'm a newbie in OpenUi5, so I might be doing something wrong and stupid here. I've started with a simplified task of passing data from the frontend to my custom control and experiencing troubles.
Background of the simplified idea:
Create a custom control with an aggregation foo , the value to it will be provided from the view.
Also create another aggregation element _searchField which will be populated with the data provided from the view.
Fire the onSuggestTerm everytime user types in a _searchField.
Custom control code:
function (Control) {
var DropDownListInput = Control.extend('xx.control.DropDownListInput', {
metadata: {
defaultAggregation: 'foo',
aggregations: {
foo: { type: 'sap.m.SuggestionItem', multiple: true, singularName: 'suggestionItem' },
_searchField: { type: 'sap.m.SearchField', multiple: false, visibility: 'hidden' }
}
}
});
DropDownListInput.prototype.init = function () {
var that = this;
this.onSuggestTerm = function (event) {
var oSource = event.getSource();
var oBinding = that.getAggregation('foo');
oBinding.filter(new sap.ui.model.Filter({
filters: new sap.ui.model.Filter('DISEASE_TERM', sap.ui.model.FilterOperator.Contains, ' Other')
}));
oBinding.attachEventOnce('dataReceived', function () {
oSource.suggest();
});
};
this.setAggregation('_searchField', new sap.m.SearchField({
id: 'UNIQUEID1',
enableSuggestions: true,
suggestionItems: that.getAggregation('foo'),
suggest: that.onSuggestTerm
}));
};
return DropDownListInput;
}, /* bExport= */true);
I'm not providing Renderer function for control here, but it exists and this is the most important excerpt from it:
oRM.write('<div');
oRM.writeControlData(oControl);
oRM.write('>');
oRM.renderControl(oControl.getAggregation('_searchField'));
oRM.write('</div>');
Passing the data to this control from the xml frontend:
<xx:DropDownListInput
id="diseaseTermUNIQUE"
foo='{path: db2>/RC_DISEASE_TERM/}'>
<foo>
<SuggestionItem text="{db2>DISEASE_TERM}"
key="{db2>DISEASE_TERM}" />
</foo>
</xx:DropDownListInput>
The code fails to run with this error Cannot route to target: [object Object] -
and I have no idea what's wrong here..
The problem is that you forgot to provide single quotes in your path:
foo="{path: 'db2>/RC_DISEASE_TERM/'}"

Data Tables are not loading when i redirect my page using self.do_action in odoo(openERP7) qweb screen

When i redirect my page using self.do_action in odoo(openERP7) it is not loading Data Tables in the new page.
In other pages it was working fine. But in a particular page if i redirect using this self.do_action is not working. But self.act_window is working fine in the same page.
If any one faced this same issue please let me know.
Update:I found a similarity of problems in my code. I have a model like performance.review and some other models also. All the self.do_action used in this model is not loading Data tables properly. But other model screens does perfectly.
Is there any relation between model extension and using self.do_action?
Here is my code,
module.ReviewForm= instance.web.Widget.extend({
events: {
'click #review_tree_view':'load_tree_view',
},
load_tree_view: function (event) {
var self = this;
self.do_action({
type: 'ir.actions.client',
tag: "performance.review",
name:'Tree view',
target: 'current',
});
},
In the javascript file, you could add an event to a buttons class name like this:
bind_events: function () {
this.$('.oe_btn_class_name').on('click', this.on_call_new_view_function);
},
Then the "on_call_new_view_function" is called when a click event occurs and opens the new view like this:
on_call_new_view_function: function () {
var self = this;
// you can pass in other data using the context dictionary variable
var context = {
'id': this.id,
};
// the action dictionary variable sends data in the "self.do_action" method
var action = {
type: 'ir.actions.act_window',
res_model: 'model.name',
view_id: 'view_id',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: context,
};
// self.do_action accepts the action parameter and opens the new view
self.do_action(action);
},
Actually this is a small mistake done by myself. Im using the same model for many qweb screens, and each time Im rendering form view using self.do_action I did't emptying the existing tree view.
It can be easily done by adding this line.
Now data tables loading properly and perfectly.
load_tree_view: function (event) {
var self = this;
self.$el.empty();
self.do_action({
type: 'ir.actions.client',
tag: "performance.review",
name:'Tree view',
target: 'current',
});
},

Feature Card Printer using Rally SDK 2

All
I am working on a feature printing app for Rally so we can generate cards for our analog portfolio kanban board. I wanted to build this printer using the 2.0 SDK. I am usign the original Card print code as my starting spot. My Java Script is rusty and i could us some help getting past this hurdle.
Goals of the App.
Get Data from Rally
Render HTML page with date in for of a card
Handle Printing
I am using a store to pull the data from Rally. This is working as expected.
I am having issue passing the store results in to the array to create the HTML cards. The data is making it to the _displayFeatureCard: function. I can see it in the console print out.
Here is what i have so far.
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function () {
console.log("App Launched")
//App Calls the portfolio feature data store
this._getfeaturedatastore();
},
//Get the portfolio feature data from Rally
_getfeaturedatastore: function(){
var getfeaturedata = Ext.create('Rally.data.wsapi.Store', {
model: 'PortfolioItem/Feature',
autoLoad: true,
//Create Fillter for the Store
filters: [
{
property: 'State.Name',
value: 'Story Definition',
}
],
listeners: {
load: function(getfeaturedatastore, getfeaturedatadata, success) {
console.log("Got Feature Data Woot",getfeaturedatastore, getfeaturedatadata, success)
this._displayFeatureCard(getfeaturedata);
},
scope: this
},
fetch: ['State', 'Name', 'Description', 'Owner', 'Parent','PlannedStartDate','FormattedID','Tags']
});
},
_displayFeatureCard: function(getfeaturedata){
var MAX_NAME_LEN = 115;
var name,i,theMarkup,data, description, owner, parent, plannedstartdate, formattedid, data;
data = getfeaturedata;
console.log("Woot made it to the Card", data)
for (i = 0; i < data; i++) {
name = data[i].Name;
owner = data[i].Owner;
parent = data[i].Parent;
description = data[i].Description;
plannedstartdate=data[i].PlannedStartDate;
formattedid=data[i].FormattedID;
theMarkup = this.createMarkup(i, data, name, description, owner, parent, plannedstartdate, formattedid);
dojo.byId("cards").innerHTML += theMarkup;
}
},
Checking your code, your app constructor is using Rally's AppSDK 2.0 (ExtJS based), while your _displayFeatureCard method is referencing dojo, which is legacy AppSDK1 and not recommended for use in AppSDK 2.0.
There is a RallyCommunity app for printing Feature Cards (a slightly modified version of PrintStoryCards). It is available here:
https://github.com/RallyCommunity/feature-print-cards
It is also based on the legacy and deprecated AppSDK1. However it still works, and you may find that it meets your requirements.

How to "react" on data changes with RxJS?

RxJS beginner here: I have problems with saving and tracking data changes using RxJS. Say I structure my app in small views/widgets and every view/widget has its own state and should do things on data changes. How do I do that?
More concrete example. Let's say I have a widget called Widget and Widget has a title and button. The state should contain the title and the information if the button was already clicked. From reading the docs of RxJS it seems this would be a good starting point:
var widgetState = new Rx.Subject().startWith({
wasClicked: false,
title: 'foo'
});
Now I want to be notified if some data changes:
var widgetStateChanges = widgetState.subscribe(function(data) {
console.log('data: ', data);
// what do i do with the data here?
// i would like to merge the new data into the old state
});
widgetStateChanges.onNext({ title: 'bar' });
I listen to the changes, but I don't know how to save them. I would also like to do special things, if a certain data change happens. Something like this.
widgetStateChanges.filter(function(e) {
return e.wasClicked;
}).do(function(e) {
console.log('Do something because was clicked now.');
});
However I can't filter a subscription (widgetStateChanges), only a subject (widgetState).
Use a BehaviorSubject to track observable state:
var widgetState = new Rx.BehaviorSubject({ wasClicked: false, title: 'foo' });
// change state, probably in response to UI events
// Note we always set the full state, not just the "delta"
widgetState.onNext({ wasClicked: true, title: 'foo2' });
// example listening to title input field and updating state
// assumes rxjs-jquery
$("#title").onAsObservable("change").subscribe (function (ev) {
var oldState = widgetState.value;
var newTitle = $("#title").val();
// do not mutate the oldState object, instead clone it and change the title
var newState = $.extend({}, oldState, { title: newTitle });
// send the update
widgetState.onNext(newState);
});
// listen to new state values, probably to update your HTML?
widgetState.subscribe(function (newState) { ... });
// listen only when wasClicked is true
widgetState
.filter(function (s) { return s.wasClicked; })
.subscribe(function (s) { ... });

How to disable cache / touch server on every node expand in Dojo tree?

I have a JsonRest connected to a dijix.Tree. The nodes are lazy loaded. that's how my tree looks like:
var store = new Observable(new JsonRest({
target: "...",
idProperty: "id",
mayHaveChildren: function(object) {
return object.hasChildren;
},
getChildren: function(object, onComplete, onError) {
this.get(object.id).then(function(fullObject) {
object.children = fullObject.children;
onComplete(fullObject.children);
}, onError);
},
getRoot: function(onItem, onError) {
this.get("I1").then(onItem, onError);
},
getLabel: function(object) {
return object.name;
}
}));
The first time I expand a tree node, the request is being sent to the server to get the node's children.
However, this call is cached, so next time I expand the node, no request is being sent. I also noticed that the getChildren function is called only once, on first expand.
What I'd like to achieve is to disable the cache, ie. send the request each time I expand the node.
In fact, it is possible. Analyzing the code of Dojo's Tree.js, led me to the conclusion, that the function that is called on every node expand is
_expandNode: function(/*TreeNode*/ node)
The function contains the following code:
// Load data if it's not already loaded
if(!node._loadDeferred){
// load the node
}
Our culprit is the _loadDeferred property, of course. So the question was, how to set this property for each expanded node.
I decieded to do that in getChildren method. First I needed to get the tree node based on item from the store and then I had to set its property to false.
I found out that tree.getNodesByItem(item) does to first part. The only thing to remember is it returns an array of nodes, so we need to take the first element:
tree.getNodesByItem(item)[0]
Now it's only a matter of setting the property:
tree.getNodesByItem(item)[0]._loadDeferred = false;
So, the final solution is
var store = new Observable(new JsonRest({
target: "...",
idProperty: "id",
mayHaveChildren: function(object) {
return object.hasChildren;
},
getChildren: function(object, onComplete, onError) {
this.get(object.id).then(function(fullObject) {
object.children = fullObject.children;
onComplete(fullObject.children);
tree.getNodesByItem(object)[0]._loadDeferred = false;
}, onError);
},
getRoot: function(onItem, onError) {
this.get("I1").then(onItem, onError);
},
getLabel: function(object) {
return object.name;
}
}));

Categories