Update list dom only if list displayed - javascript

Sometimes we use one store for few views(list, carousel,dataviews) and when we refresh(load, filter) store data, dom of all view that use this store will be rebuild, but some views is not displayed in this time, and may be will not show with these data. How we can refresh list dom only if it displayed, not every time when it store refresh?
Issue examle
Ext.define("Test.view.Main", {
extend: 'Ext.tab.Panel',
config: {
tabBarPosition: 'bottom',
items: [ ]
},
constructor : function(){
this.callParent(arguments);
var store = Ext.create('Ext.data.Store',{
data :[
{title : 'One'},
{title : 'Two'},
{title : 'Three'}
]
}),
firstList = Ext.create('Ext.List',{
title : 'tab1',
store : store,
itemTpl : '{title}',
onItemDisclosure : function(){
store.add({title : 'Four'});
}
}),
secondList = Ext.create('Ext.List',{
title : 'tab2' ,
store : store,
itemTpl : '{title}'
}),
thirdList = Ext.create('Ext.List',{
title : 'tab3',
store : store,
itemTpl : '{title}'
});
this.add([
firstList,
secondList,
thirdList
]) ;
}
});
When tap on item in the first list, in store will be added new item. And dom of all list will be change although second and third list not displayed
I see one option. Create one main store and create separate stores for each views. And when view show fill it store from Main store. But it look not good. Any other ideas?

As far as I know, there is no "out-of-the-box" solution. The docs say that the refresh event is preventable, but I haven't tested that theory.
One other idea would be to look at the dataview source and override parts of it.
The starting point would probably be to look at the store event hooks that you can find there:
storeEventHooks: {
beforeload: 'onBeforeLoad',
load: 'onLoad',
refresh: 'refresh',
addrecords: 'onStoreAdd',
removerecords: 'onStoreRemove',
updaterecord: 'onStoreUpdate'
}
However it would probably be tedious work perfecting it.
On the other hand, your DOM shouldn't be refreshed for the other lists when adding a new record, it should only add a new list item to each list so disabling the addrecords event and then doing a complete refresh of the other lists when they are displayed will probably be more ineffective?

Related

How to get the associated store in Sencha Touch?

Hi I am working with Sencha Touch app, and I have in a one store called "Customers" one model associated, I know when you create a model associated, automatically you create a new store in background, my question is: How to get this store called "templatesStore" (I see the result in the Chrome console) to filter later?
Thank you in advance.
It can be done using following syntax:
<mainStore>.getAt(0).<assosiationName>();
For example,if main store is "Customer" & name given in association as 'Template' then:
Association given in Customer model:
hasMany: [
{
model: 'sample.model.Template',
associationKey: 'templates',
name: 'templates' // name given here will be accessed from main store
},
]
For getting the template store:
Ext.getStore('Customer').getAt(0).templatesStore;
or
Ext.getStore('Customer').getAt(0).templates();
For filtering 'Customer' store based on template value:
Ext.getStore('Customer').filter([
{ filterFn: function (item) {
item.templatesStore.filter('templateValue',templateValue); // templateValue contains the value of selected template
if(item.templatesStore.getCount()>0)
return true;
else
return false;
}
}
]);

ExtJS 5 - Dynamically add items to split button menu from store

I want to associate a store to split button menu. I am using extjs version 5. I have searched on the web and even went through sencha documentation but I couldn't figure out a way to achieve this.
Currently i'm holding the menu details in variable and assigning it to the splitbutton xtyoe menu property.I want to achieve the same using store, your help is much appreciated!
Program Code:-
var menuJSON = [{
text:'Menu1',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu2',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu3',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
},{
text:'Menu4'
},{
text:'Menu5',
menu:[{text:'Submenu1'},{text:'Submenu2'}]
}];
{
region: 'south',
fbar: [{
xtype:'splitbutton',
id: 'app-starterMenu',
text:'Start',
scale:'small',
iconCls:'icon-start',
menuAlign: 'bl-tl',
menu: menuJSON
}]
}
Thanks in advance!
It would be helpful if you can provide example code for the store or relative controller, however this is still easier than you might think. Of course, it's nothing that comes out of the box, but it's a perfect case of using listeners.
Whenever the store changes data, you want to update your button configuration. Therefore just add the relevant listener to your store - maybe using the refresh or update event (depending on your specific use case). Then whenever the store data changes, you need to grab a reference to your button (or associated menu) and update the items. In it's most simplistic form, an example might be as follows:
store: {
listeners: {
refresh: function(store) {
// Get all the raw data from records and use it to set items on the menu
var rawData = Ext.Array.pluck(store.getRange(),'data');
Ext.getCmp('app-starterMenu').setMenu({
items: rawData
});
// *OR* Loop through the store data conditionally and include what you need
Ext.getCmp('app-starterMenu').getMenu().removeAll();
store.each(function(record){
Ext.getCmp('app-starterMenu').getMenu().add(record.getData());
});
}
}
}

Enyo MVC implementation and particle view rendering

Could you please help me with MVC implementation with enyojs framework
The current goal is to implement N -panels (displays, windows) for TV application which would be changed after button was pressed (channel switch for instance). It looks just like simple redirect to new URL (or controller's action) in web. So, we want to re-render views and parts of views and update windows(panels) using strategy of keeping just 2 displays at the same time (current and next we go with animation). I learned some examples of MVC with enyo from other topics here, but that implementations of MVC but some questions are still exist.
Problem: how to implement in enyo the particle updating of the view with new data from controller ?
//--- app.js
enyo.kind({
name: "my.Application",
kind: "enyo.Application",
view: "Index", // default start view
controllers: [ // I use 2.3 version and know about this rudiment property.
{name: "homeController", kind: "HomeController"}
],
viewChanged : function() {
this.inherited(arguments);
app.render(); // this updates the view. Changes from index to edit and back.
}
});
enyo.ready(function () {
app = new my.Application({name: "app"});
});
//------ controller.js + IndexView.js + editview.JS
enyo.kind({
name : "IndexView",
kind: "enyo.View",
components: [
{content: "HelloWorld, This is Index"},
{content: "This is the Index view"},
{kind: "moon.ToggleButton", content: "Show Edit", ontap: "buttonTapped"}
],
// redirect to Edit View
buttonTapped: function(sender, event){
app.controllers.homeController.Edit("message(model) to Edit View");
}
});
enyo.kind({
name : "EditView",
kind: "enyo.View",
message: "no msg",
components: [
{name: "headWithId", content: "Hello! This is EDIT."},
{content: "This is the Edit view"},
{kind: "moon.ToggleButton", content: "Show Index", ontap: "buttonTapped"}
],
bindings: [
{from: ".message", to:".$.headWithId.content"}
],
// redirect to Index View
buttonTapped: function(sender, event){
app.controllers.homeController.Index();
}
});
enyo.kind({
name : "HomeController",
kind: "enyo.Controller",
Index : function(){
app.set("view", new IndexView()); // this code updates the view of app, but maybe there is a better way to do it?
},
Edit : function(msg){
app.set("view", new EditView({message: msg}));
}
});
The previous code works find. There some question in comments. But how to implement such situation, then I don't want to rerender all the divs of the view, but just particle content (for example, leave the header and update the content):
// ----- baselayoutview.js
enyo.kind({
name : "BaseLayout",
kind: "enyo.ViewController", // or enyo.View... what is better?
components: [
{content: "this content of the View never changes"},
// next content should be changed. It's for renderTarget
{name: "RenderContentSection"} // How to render new content form Index or Edit view here?
]
});
// ----- app.js
enyo.kind({
name: "my.Application",
kind: "enyo.Application",
view: "BaseLayout", // We set this base layout view and expect the it will fill it's content by itself
controllers: [
{name: "homeController", kind: "HomeController"}
],
viewChanged : function() {
this.inherited(arguments);
app.render("RenderContentSection"); // I think it would not be working any more.. but what it the best way to do it? How to update BaseLayout view's RenderContentSection ?
}
});
You should not be calling app.render() to re-render your application. As you say, you don't want to re-render the whole thing each time. Are you stuck on Enyo 2.3 or can you update to a more recent version? Controllers have been largely deprecated, for one.
I suggest taking a look at the Panels component. You can place a Panels component within your area that changes and navigate to a panel and push whatever content you want into that panel. You individual sections would be Panel components and you can push and pop those as needed. If you need to replace the panel.
If you really want to do it that way, you can modify your BaseLayout component so that it uses createComponent() to create whichever partial view you want.
enyo.kind({
name : "BaseLayout",
// This can be just a plain enyo.Control
components: [
{content: "this content of the View never changes"},
// next content should be changed. It's for renderTarget
{name: "renderContentSection"} // How to render new content form Index or Edit view here?
],
replacePartial: function(partial) {
this.$.renderContentSection.destroyClientControls();
this.$.renderContentSection.createComponent({kind: partial});
this.$.renderContentSection.render();
}
});
Here's a fiddle showing that off: http://jsfiddle.net/RoySutton/LhjLv6hy/
You could create a new control with a 'chrome' controls and a client area that controls get rendered into, but this is pretty simple. Still, take a look at Panels. It's what they were designed for.

sencha touch load store manually

Simple use case: I want to manually control when I load the store. When the store is loaded, I want the data to populate the list. However, I cannot get it to work.
When I set autoLoad to true on the store, it works. If I remove autoLoad, and add this to the view nothing happens.
List config:
{
xtype: 'list',
fullscreen: true,
disableSelection: true,
store: 'NewsStore',
itemId: 'newsList',
itemTpl: '<li><strong>{date} - {title}</strong><br/>{text}</li>',
plugins: [
{
xclass: 'Ext.ux.touch.PullRefreshFn',
pullText: 'Henter nyheter',
refreshFn: function () {
Ext.getStore('NewsStore').load();
}
}
]}
The listener on the panel will load the store:
listeners: {
painted: function () {
Ext.getStore('NewsStore').load();
}
}
I have tried to use the callback from the load method. I have tried to get the store from the list and update this, nothing works (the list is simply empty and does not display anything, even though I can see that the code is fetching the information). Any idea what I am doing wrong here?
You have to use setStore property to populate the data
var myStore = Ext.getStore('NewsStore');
Now access the list object and just
mylist.setStore(myStore);

How to display associated models in separate Ext grids?

I have two associated models, User and Order. A User has many Orders.
Ext.define("User", {
extend: 'Ext.data.Model',
fields: [
'id', 'name'
],
hasMany: {model: 'Order', name: 'orders'},
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});
Ext.define("Order", {
extend: 'Ext.data.Model',
fields: [
'id', 'total'
],
belongsTo: 'User'
});
I'd like to display all of the Users in one grid panel, and all of the orders in another grid. I know how to show all of the Users in a grid, I simply define a store with the User model. But I'm a bit lost as to how to show all of the orders in a separate grid. Do I have to define a separate store? What proxy do I use? Anyone have insight? Basically, I just need a conceptual understanding.
I believe what you are asking for is a fairly common use case. Unfortunately ExtJs is not yet able to cope with this out of the box, simply as currently each grid is bound to a store, but your orders store is created on the fly every time you access it through its user association.
The good news is that you have various ways to achieve this. The best one I can think of is that every time the user clicks on a user row, you get your orders store (user.orders()). Then you can reconfigure your grid with this new store.
Usually each Grid needs its own Store. Showing all orders will work the same way as showing all users, just change the Store ID and it should be okay.

Categories