I can successfully save data to local storage and retrieve it. However, if I refresh my browser and then try to recall the data in local storage, it fails to do so.
I am saving the data like so;
var eventStore = Ext.getStore('Details');
if(null == eventStore.findRecord('id', currentEvent.data.id)) {
eventStore.add(currentEvent);
}
eventStore.sync();
eventStore.sort([{ property: 'dateCreated', direction: 'Desc' }]);
console.log('Data saved, store has ' + eventStore.getCount() + ' items');
console.log(localStorage);
When i refresh my browser and check my console, the entry is there, but when i try to call it like below, it fails.
var store = Ext.getStore('Details');
var storeId = store.findRecord('id', 'LC');
console.log('Details store has ' + store.getCount() + ' items');
console.log(storeId.data.id);
return;
i am new to Sencha touch and would greatly appreciate any advice as to what I'm doing wrong.
You have to check property phantom: true of the new created model. If it is not set or is false the proxy will not synchronize it is remote store, but keeps only in store's 'memory' :)
I'd advise save your event record via model.save() rather than store's sync() call. Have a look at http://docs.sencha.com/touch/2-0/#!/api/Ext.data.Model-method-save. Proxy can be defined for Model as far as for Store.
Cheers, Oleg
Problem solved!
Simply updated sencha touch to the latest version and all works as should.
Related
I'm building an app with titanium and I would like to save in the phone, the user's profile picture. In my login function, after the API response, I tried to do :
Ti.App.Properties.setString("user_picture_name", res.profil_picture);
var image_to_save = Ti.UI.createImageView({image:img_url}).toImage();
var picture = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, res.profil_picture); //As name, the same as the one in DB
picture.write(image_to_save);
And in the view in which I want to display the image :
var f = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory,Ti.App.Properties.getString("user_picture_name") );
var image = Ti.UI.createImageView({
image:f.read(),
width:200,
height:100,
top:20
});
main_container.add(image);
But the image doesn't appears. Could someone help me ?
Thanks a lot :)
There are 2 issues with your code:
1 - You cannot use toImage() method unless your image view is rendered on UI stack or simply on display. Rather you should use toBlob() method.
2 - Point no. 1 will also not work the way you are using because you cannot directly use toBlob() method until or unless the image from the url is completely loaded, means until it's shown on image view. To check when the image is loaded, use Ti.UI.ImageView onload event
But, there's another better approach to do such type of tasks.
Since you have the image url from your Login API response, you can use this url to fetch image from http client call like this:
function fetchImage() {
var xhr = Ti.Network.createHTTPClient({
onerror : function() {
alert('Error fetching profile image');
},
onload : function() {
// this.responseData holds the binary data fetched from url
var image_to_save = this.responseData;
//As name, the same as the one in DB
var picture = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, res.profil_picture);
picture.write(image_to_save);
Ti.App.Properties.setString("user_picture_name", res.profil_picture);
image_to_save = null;
}
});
xhr.open("GET", img_url);
xhr.send();
}
You don't need to manually cache remote images, because
Remote images are cached automatically on the iOS platform and, since
Release 3.1.0, on the Android platform.
[see docs here & credit to Fokke Zandbergen]
Just use the remote image url in your UI, at first access Titanium will download and cache it for you; next accesses to the same image url will actually be on the automatically cached version on local device (no code is best code)
Hth.
So my problem is this. I can remove a record from localstorage proxy just fine the first time. But if I do it again, it gives me an error, where everything in the Store is undefined, like it didnt exist anymore.
onTapRemoveKegelReminder: function(button) {
console.log(button.getData());
//Find and delete the button and the record
var store = Ext.getStore('KegelReminders');
store.load();
store.filter('button_id', button.getData());
var record = store.first();
console.log(record);
console.log(button.getData());
console.log('Remove count'+ store.getCount());
if (typeof record !== 'undefined'||record!=null ) {
store.remove(record);
store.sync();
console.log('removed record correctly')
this.trainingCount--;
var rmButton = this.getKegelExercises().down('#container-' + button.getData());
this.getKegelExercises().remove(rmButton);
}
But if I restart my application, and then remove again it works fine. I cant seems to remove more than once without having to restart the application.
FYI in case anyone else finds this, removing a record from a Store only removes it from that instance of the store, not from the storage mechanism (for example, localstorage). If you want to do that you have to use the erase method on the model object.
store.remove(record); // may not even be necessary
record.erase();
store.sync();
I'm trying to work on the "different permissions based on workflow state" issue but I'm struggling with the fact that it seems impossible to get the id of the current object 'at any time' that is necessary in order to get the permission of that object. What I mean is that I manage to get it from the client state following jquery bbq docs like:
$.bbq.getState().id
BUT it looks like this is doable only AFTER a complete page load. I investigated this by placing some alert in the main view events, like:
openerp.web.PageView = openerp.web.PageView.extend({
on_loaded: function(data) {
this._super(data);
alert('page load ' + $.bbq.getState().id);
},
do_show: function() {
this._super();
alert('page show ' + $.bbq.getState().id);
},
reload: function() {
this._super();
alert('page reload ' + $.bbq.getState().id);
},
on_record_loaded: function(record) {
this._super(record);
alert('record loaded ' + $.bbq.getState().id);
}
});
and I found that when you open the page view (by clicking on an item in a search view, for instance) you get always "undefined".
Then, you get it into "reload" and "on_record_loaded" when passing from an object to another using paged navigation. And then, you miss it again when you click on the "edit" button.
In the form view I successfully got it only on the 1st load because it seems that some caching is in-place. So that, if I place a pdb into web client's fields_view_get and I do this into the form "init_view":
var ids = [];
if ($.bbq.getState().id){
ids = [parseInt($.bbq.getState().id)];
}
console.log(ids);
return this.rpc("/web/view/load", {
"model": this.model,
"view_id": this.view_id,
"view_type": "form",
toolbar: this.options.sidebar,
context: context,
ids: ids,
}, this.on_loaded);
I get it only the 1st time that the page gets loaded. The same happen if I take ids from
this.dataset.ids
I looked anywhere at the core web module and I can't find a proper API for this and it looks weird (above all on dataset) that we don't have a proper way for getting/working on the current record/s. Even the context and the session do not have any information about that.
Probably I should store this into the view itself on 1st load...
Thanks in advance for any pointers.
try:
this.view.datarecord.id
OpenERP 7 in form view:
debugged using google chrome
Try the combination of the
this.dataset.ids and this.dataset.index
like
curr_id = this.dataset.ids[this.dataset.index]
this might solve your problem.
I have and application that uses NestedList with a TreeStore. TreeStore is using AJAX type proxy and XML reader. Now I have implemented Settings page, where you can change the URL that is used as a data source. Application needs to "reload" after that change. As a result, I change proxy URL:
App.tree_store.proxy.url = new_url;
Then I would like to load a new data:
App.tree_store.load();
When I switch NestedList to root card, it will contain mixed data from previous configuration and current one:
App.views.hdTreeView.setActiveItem(0);
Question: How should I "clear/reset" NestedList before loading entirely new data (same data model)? Do I have to clear TreeStore / SubStores and Proxy as well, if yes, how? Maybe using destroy() method and recreate new components?
If I remove all lists using removeAll() and than reload store, new list will not be created.
Thanks!
showDetail: function(list, index , element , record) {
//Take your store
var store = Ext.getStore('yourstore');
//Apply the params
Ext.apply(store.getProxy()._extraParams, {
id : record.data.id
});
//Reload your store
store.load();
}
put this code at controller
just change extraParams to fetch new data.
in store dont input exterparam.
so u cab use just one url but chnage just param for fetch data.
First use store.setProxy() and pass new proxy object then use this:
nestedListObject.bindStore(store.load());
where the nestedListObject is your nested list.
I've been trying to send data from my background page to a content script in my chrome extension. i can't seem to get it to work. I've read a few posts online but they're not really clear and seem quite high level. I've got managed to get the oauth working using the Oauth contacts example on the Chrome samples. The authentication works, i can get the data and display it in an html page by opening a new tab.
I want to send this data to a content script.
i'm having a lot of trouble with this and would really appreciate if someone could outline the explicit steps you need to follow to send data from a bg page to a content script or even better some code. Any takers?
the code for my background page is below (i've excluded the oauth paramaeters and other )
` function onContacts(text, xhr) {
contacts = [];
var data = JSON.parse(text);
var realdata = data.contacts;
for (var i = 0, person; person = realdata.person[i]; i++) {
var contact = {
'name' : person['name'],
'emails' : person['email']
};
contacts.push(contact); //this array "contacts" is read by the
contacts.html page when opened in a new tab
}
chrome.tabs.create({ 'url' : 'contacts.html'}); sending data to new tab
//chrome.tabs.executeScript(null,{file: "contentscript.js"});
may be this may work?
};
function getContacts() {
oauth.authorize(function() {
console.log("on authorize");
setIcon();
var url = "http://mydataurl/";
oauth.sendSignedRequest(url, onContacts);
});
};
chrome.browserAction.onClicked.addListener(getContacts);`
As i'm not quite sure how to get the data into the content script i wont bother posting the multiple versions of my failed content scripts. if I could just get a sample on how to request the "contacts" array from my content script, and how to send the data from the bg page, that would be great!
You have two options getting the data into the content script:
Using Tab API:
http://code.google.com/chrome/extensions/tabs.html#method-executeScript
Using Messaging:
http://code.google.com/chrome/extensions/messaging.html
Using Tab API
I usually use this approach when my extension will just be used once in a while, for example, setting the image as my desktop wallpaper. People don't set a wallpaper every second, or every minute. They usually do it once a week or even day. So I just inject a content script to that page. It is pretty easy to do so, you can either do it by file or code as explained in the documentation:
chrome.tabs.executeScript(tab.id, {file: 'inject_this.js'}, function() {
console.log('Successfully injected script into the page');
});
Using Messaging
If you are constantly need information from your websites, it would be better to use messaging. There are two types of messaging, Long-lived and Single-requests. Your content script (that you define in the manifest) can listen for extension requests:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == 'ping')
sendResponse({ data: 'pong' });
else
sendResponse({});
});
And your background page could send a message to that content script through messaging. As shown below, it will get the currently selected tab and send a request to that page.
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: 'ping'}, function(response) {
console.log(response.data);
});
});
Depends on your extension which method to use. I have used both. For an extension that will be used like every second, every time, I use Messaging (Long-Lived). For an extension that will not be used every time, then you don't need the content script in every single page, you can just use the Tab API executeScript because it will just inject a content script whenever you need to.
Hope that helps! Do a search on Stackoverflow, there are many answers to content scripts and background pages.
To follow on Mohamed's point.
If you want to pass data from the background script to the content script at initialisation, you can generate another simple script that contains only JSON and execute it beforehand.
Is that what you are looking for?
Otherwise, you will need to use the message passing interface
In the background page:
// Subscribe to onVisited event, so that injectSite() is called once at every pageload.
chrome.history.onVisited.addListener(injectSite);
function injectSite(data) {
// get custom configuration for this URL in the background page.
var site_conf = getSiteConfiguration(data.url);
if (site_conf)
{
chrome.tabs.executeScript({ code: 'PARAMS = ' + JSON.stringify(site_conf) + ';' });
chrome.tabs.executeScript({ file: 'site_injection.js' });
}
}
In the content script page (site_injection.js)
// read config directly from background
console.log(PARAM.whatever);
I thought I'd update this answer for current and future readers.
According to the Chrome API, chrome.extension.onRequest is "[d]eprecated since Chrome 33. Please use runtime.onMessage."
See this tutorial from the Chrome API for code examples on the messaging API.
Also, there are similar (newer) SO posts, such as this one, which are more relevant for the time being.