Store/List not reloading Sencha 1.1.1 - javascript

I've got a phonegap-wrapped sencha touch (v1.1.1) app that has a few stores, and a list.
The problem occurs after you're logged in as "User1", and then log out and log back in as "User2". The list won't refresh with the new account data fetched by the store proxy.
I'm currently attempting to call .refresh() on the List itself, which according to the docs will also cause the store to refresh its data (although, I'm manually doing that before hand anyway)
var sL = Ext.getCmp('AccountsList');
sL.refresh();
sL.scroller.scrollTo({x:0,y:0});
We've also tried to .sync() the stores with no results.
Ext.getStore('AccountsTransfersTo').sync();
Ext.getStore('AccountsTransfersFrom').sync();
Ext.getStore('AccountsStore').sync();
Any idea what the problem is, or has anyone run into something similar?

refresh won't reload the store, it just grabs whatever is in the store and re-renders the view.
sync is for updating the store when you've got local changes and you're posting them to the server.
You need to call the load method on the store.

It sounds like a caching problem. or a state problem.
a link:
http://html5wood.com/sencha-touch-difference-between-ext-get-and-ext-getcmp/
from the page:
Sencha Touch: Difference between Ext.get() and Ext.getCmp()
Important: It returns the same element object due to simple caching on retrieving again. It means it returns wrong element on second time. Ext.fly() can be used for avoiding this problem.
hope it helps
mike.

You may Load the store each time
var sL = Ext.getStore('AccountsTransfersTo')
sL.load();
sL.scroller.scrollTo({x:0,y:0});
or you may try to clear data form store and reload it again
var sL = Ext.getStore('AccountsTransfersTo')
sL.removeAll();
sL.load();
sL.scroller.scrollTo({x:0,y:0});

Related

How can we use the same state across multiple tabs (pages)?

I have a page in my application that is an interactive chart with a bunch of settings (filters, time ranges, etc). I'd like to store them in-app state because some of the settings may be used by other components on another page, but right now if I click on any other tab and come back to the previous tab then the page shows the initial state(chart is gone, filtered data gone, date range showing the default value, dropdowns shows default ass well). And the state is also showing null.
Anything in your component state is dynamic; i.e., it is temporary. If you refresh the window, the old state is lost. A similar thing happens when you open a fresh tab—you get the state declared in your constructor. You can use any of the following if you want the state data in another tab:
Simply using redux won't solve your problem as redux store is also related to a specific browser tab. If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware. Check out the redux-persist, redux-storage middleware.
If you are using react-router you can simply pass required state through the link when you open a fresh tab. Here's an example:
<Link to={{
pathname: '/pathname',
state: { message: 'hello, im a passed message!' }
}}/>
Simply store the data in localStorage and access localStorage in other tabs.
If you are looking to use a variable across the entire application you can also use localStorage
localStorage.setItem('move', this.state.move);
also don't forget to unset it when you are done!
localStorage.removeItem('move');
The straight forward solution to this is redux-state-sync. It will just work and the store will be updated on all tabs and even windows on the browser.
I think you should implement react-redux into your app.
React-redux is a state management tool that manage the state of your application at a centralized location and you access data from store at anytime from anywhere.
React-redux:
https://redux.js.org/basics/usage-with-react
You some library for state management. The most popular one that's used with React is redux.
https://redux.js.org/introduction

Update data in (really) real-time with Javascript

hi
I want to build a control panel for a web art application that needs to run in fullscreen, so all this panel, that controls stuff like colors and speed values, have to be located at a different window.
My idea is to have a database storing all these values and when I make a change in the control panel window the corresponding variable in the application window gets updated too. So, it's basically a real-time update that I could do with AJAX setting a interval to keep checking for changes BUT my problem is: I can't wait 30 seconds or so for the update to happen and I guess a every-1-second AJAX request would be impossible.
Final question: is there a way to create a sort of a listener to changes in the database and fire the update event in the main application only immediately after I change some value in the control panel? Does Angular or another framework have this capability?
(Sorry for the long explanation, but I hope my question is clearer by offering the context [: )
A web socket powered application would have this benefit. This carries a bit more complexity on the back end, but has the benefit of making your application as close to real-time as can be reasonably expected.
The Mozilla Development Network has some good documentation on websockets.
On the front end, the WebSocket object should work for you on most modern browsers.
I'm not sure what your back end is written in, but Socket.IO for Node.js and Tornado for Python will make your applications web-socket capable
If one window is opening the other windows via JavaScript, you can keep the reference to the opened window and use otherWindow.postMessage to pass messages across
"Parent" window looks like
// set up to receive messages
window.addEventListener('message', function (e) {
if (e.origin !== 'http://my.url')
return; // ignore unknown source
console.log(e.message);
});
// set up to send messages
var otherWindow = window.open('/foo', '_blank');
otherWindow.postMessage('hello world', 'http://my.url');
"Child" windows look similar
// same setup to recieve
// ...
// set up to send
var otherWindow = window.opener;
// ... same as before
For the realtime I would recommend using a library like socket.io or using a database like firebase.
For the fullscreen I would recommend using a library like angular-screenfull
i use https://pushjs.io/, had exactly the same problem and this is a really simple solution for your problem. It is capable of sending and listening to events without any database interference.

React routing and persistence on page refresh

I am using React with react-router and Reflux as my datastore, but I am unsure on how to best deal with persistence to allow page refresh.
My components connect to the store with Reflux.connect, but since the store fetches the data from a backend, it is not available yet when the Components first initialize and render.
When the user enters my app from the start, then all this data is loaded in order and available when it needs to be, but if further down a route you trigger a page refresh, react tries to render components that rely on data that is not there yet.
I solved this by constantly keeping a copy of data in LocalStorage and serving that from the Reflux store getInitialState(), so that all components get the data before they render.
I wonder if this is the proper way to do it. When for some reason the local storage data gets cleared or corrupted, the interface goes blank, because the components cannot access the correct data. Substructures and properties don't exist and trigger javascript errors. It seems like a messy and unreliable solution.
I am curious to know what patterns are used to solve this.
------ edit -----
To answer to the comment of WiredPrairie:
1) Why are you initializing components with data in getInitialState?
When my components use Reflux.connect, they don't have the data in their state yet on the first render as the store still needs to fetch its data. My views currently don't work gracefully with undefined data. By returning the locally stored cache from the Reflux store in getInitialState(), all connected components will get that data before their first render call.
2) What's causing a page refresh and why can't the data be loaded in the same manner as it was the first time?
It's mainly a workaround I had to build around livereload refreshing the page when I make edits (will look into using react-hotloader later but is not an options yet), but users can also just hit refresh when they are somewhere in my nested views and that would have the same effect. When they manually refresh, they are not entering the app at the start.
3) When components are wired to the change events of a store, why don't they update then?
They do update, but like I said they don't deal with empty data right now and on first render they will miss it waiting for the store to fetch things. I can make all my views work gracefully with empty data, but that would add a lot of boilerplate code.
From the replies so far, I get the feeling that what I'm doing with localStorage is the common way to do it. Cache stuff locally in localStorage or sessionStorage or something similar, and serve that data immediately after a refresh.
I should make my views a bit more robust by gracefully handing empty data on the odd occasion that localStorage doesn't work properly.
I've been caching each Store in sessionStorage when its emitChange() fires, and initializing the store from sessionStorage if cached data exists, or null values otherwise. This seems to work provided that the views can handle null values, which is probably a good idea anyway (it sounds like this is your main problem).
I'd suggest making your views handle the case of no data gracefully, initialize everything with null values if the cache isn't available, and then call the backend to update the null values with an Action whenever the data returns.
I haven't tried Reflux, but in regular Flux it would look like this (maybe you can apply the same principle):
var _data;
if (sessionStorage.PostStore)
_data = JSON.parse(sessionStorage.PostStore);
else {
_data = {
posts: null
};
BackendAPI.getPosts(function(err, posts) {
if (posts) {
PostActions.setPosts(posts);
}
});
}
...
AppDispatcher.register(function(payload) {
var action = payload.action;
switch (action.actionType) {
...
case Constants.SET_POSTS:
_data.posts= action.data.posts;
break;
default:
return true
}
// Update cache because state changed
sessionStorage.PostStore = JSON.stringify(_data);
PostStore.emitChange();
return true;
});

Auto detect if DB table changes

I have a small application where a users can drag and drop a task in an HTML table.
When user drops the task, I call a javascript function called update_task:
function update_task(user_id, task_id, status_id, text, uiDraggable, el) {
$.get('task_update.php?user_id='+user_id+'&task_id='+task_id+'&status_id='+status_id+'', function(data) {
try {
jsonResult = JSON.parse(data);
} catch (e) {
alert(data);
return;
};
In task_update.php I GET my values; user_id, task_id & status_id and execute a PDO UPDATE query, to update my DB. If the query executes correctly, I
echo json_encode ( array (
'success' => true
) );
And then I append the task to the correct table cell
if(typeof jsonResult.success != 'undefined') {
$(uiDraggable).detach().css({top: 0,left: 0}).appendTo(el);
}
This has all worked fine. But, I'm starting to realize, that it's a problem when 2 or more people are making changes at the same time. If I'm testing with 2 browsers, and has the site opened on both for example: Then, if I move a task on browser1, I would have to manually refresh the page at browser2 to see the changes.
So my question is; How can I make my application auto-detech if a change to the DB-table has been made? And how can I update the HTML table, without refreshing the page.
I have looked at some timed intervals for updating pages, but that wouldn't work for me, since I really don't want to force the browser to refresh. A user can for example also create a new task in a lightbox iframe, so it would be incredibly annoying for them, if their browser refreshed while they were trying to create a new task.
So yeah, what would be the best practice for me to use?
Use Redis and its publish/subscribe feature to implement a message bus between your PHP app and a lightweight websocket server (Node.js is a good choice for this).
When your PHP modifies the data, it also emits an event in Redis that some data has changed.
When a websocket client connects to the Node.js server, it tells the server what data it would like to monitor, then, as soon as a Redis event was received and the event's data matches the client's monitored data, notify the client over the websocket, which then would refresh the page.
Take a look at this question with answers explaining all of this in detail, includes sample code that you can reuse.
I would use ajax to check the server at a reasonable interval. What's reasonable depends on your project - it should be often enough that it changes on one end don't mess up what another user is doing.
If you're worried about this being resource intensive you could use APC to save last modified times for everything that's active - that way you don't have to hit the database when you're just checking if anything has changed.
When things have changed then you should use ajax for that as well, and add the changes directly in the page with javascript/jquery.
If you really need to check a db changes - write a database triggers.
But if nobody, except your code, change it - you can to implement some observation in your code.
Make Observation(EventListener) pattern imlementation, or use one of existed.
Trigger events when anything meaningful happened.
Subscribe to this events

Fetch current user through store.find('users', 'me') stores invalid User instance

I am trying this solution to fetch the current user before my application is rendered to the user:
Em.Route.extend({
model: function() {
var currentUserPromise = this.store.find('user', 'me');
return Em.RSVP.all([
currentUserPromise
]);
}
});
So, I query the user with the ID me, which is a constant that my API recognizes as the currently authenticated user.
It works really well most of the way. The issue is that Ember-Data immediately creates a User model in the store with this ID constant me and no other attributes. This instance is not removed after the response has arrived and Ember-Data correctly stores the real User model.
I can't figure out where Ember-Data creates this temporary instance and if there is a way to prevent this behavior.
Either a solution to prevent Ember-Data from creating the temp. instance or remove it when the real data arrives will be fine.
Anyone with a solution?
After consulting with #emberjs I found that a much cleaner solution to this challenge is to request the active user by requesting a session object from my API.
By exposing a /sessions endpoint in my API I could expose the current session—which can also include auth token, etc.—with a relationship to the currently logged in profile. That resulted in a JSON payload like this:
{
"sessions": [
{
"id": 1,
"user": { ... },
"accessToken": "abcdef1234567890"
}
]
}
This means that I will no longer have the issue that Ember-Data caches a bogus User object with the id 'me', instead I will now have a session object where the active user is correctly loaded into the store and have it available through the session.
I think you are going about things the wrong way. You're in a single page application, which means the user can log out or log in at any time, and any rendering is essentially already happening before and after that. You can only control what you allow to render, but not the when.
Also, you are explicitly returning a set of promises which resolves when the single promise it contains is resolved. This achieves the same:
Em.Route.extend({
model: function() {
return this.store.find('user', 'me');
}
});
You don't know when that will resolve, but you're asking to "fetch the user before the app is rendered to the user". That's not how it works in Ember, as you can't really delay rendering. (Technically you can, but that offers terrible user experience giving the feeling the browser has locked up).
What you would want to do instead is to modify what you are rendering based on the state of the logged in user, and on the backend side you only ever send what that user is allowed to see. Anything else is insecure, as you can't ever trust the browser. It's pretty trivial to make an Ember app think you are logged in.
The issue is that Ember-Data immediately creates a User model in the store with this ID constant me and no other attributes.
I'm not sure about that one; I'm guessing ember-data creates a placeholder while it waits for the population of the real data (if ever). It is as if you're creating a new empty object in code.
I can't figure out where Ember-Data creates this temporary instance
Ember-data is in its core basically a cache (why it is called the store) with various adapters to read from and write to that cache and an API to use it. In your example me is created in the cache only, at least until you decide to save it.
Ember data modifies the same record instead of creating a new record after the materialization. There might be some other problem while finding the records for table. For example In ember data 1.0.0-beta.8 the the following code logs correct id rather than printing 'me'.
this.store.find('user', 'me').then(function(user) {
console.log(user.get('id'));
});

Categories