Many of the readers of this tutorial on how to build a Sencha Touch Application have requested a version of the Notes Application that shows how to create components using the config object, instead of the initialize function. In this chapter of the tutorial, we are going to do just that.
Using Sencha Touch’s Config Object to Create the Notes List
The first step we are going to take is consolidate the Notes List Container View and Notes List View into a single View, which we will call Notes List View. This View has the same components that used to exist in the former Views:

In the application’s view directory, we are going to delete the old NotesListContainer.js file, and leave only the NotesList.js and NoteEditor.js files:

Next, we are going to remove the existing code from the NotesList.js file, and define the NotesList class like so:
Ext.define("NotesApp.view.NotesList", {
extend: "Ext.Container",
requires:"Ext.dataview.List",
alias: "widget.noteslistview",
config: {
layout: {
type: 'fit'
},
items: [{
xtype: "toolbar",
title: "My Notes",
docked: "top",
items: [
{ xtype: 'spacer' },
{
xtype: "button",
text: 'New',
ui: 'action',
itemId: "newButton"
}
]
}, {
xtype: "list",
store: "Notes",
itemId:"notesList",
loadingText: "Loading Notes...",
emptyText: '<div class="notes-list-empty-text">No notes found.</div>',
onItemDisclosure: true,
grouped: true,
itemTpl: '<div class="list-item-title">{title}</div><div class="list-item-narrative">{narrative}</div>'
}],
listeners: [{
delegate: "#newButton",
event: "tap",
fn: "onNewButtonTap"
}, {
delegate: "#notesList",
event: "disclose",
fn: "onNotesListDisclose"
}]
},
onNewButtonTap: function () {
console.log("newNoteCommand");
this.fireEvent("newNoteCommand", this);
},
onNotesListDisclose: function (list, record, target, index, evt, options) {
console.log("editNoteCommand");
this.fireEvent('editNoteCommand', this, record);
}
});
If you are already familiar with the previous version of this View, you will notice that although the onNewButtonTap and onNotesListDisclose functions remain unchanged, we are now taking advantage og the config object to define the View’s items, and the event listeners needed for the New button and the disclose buttons of the notes List.
Defining Event Listeners with Sencha Touch Config Objects
The New button’s tap listener is pretty straightforward. Its delegate config is the value of the itemId config of the button. The fn config is a pointer to the onNewButtonTap function:
{
delegate: "#newButton",
event: "tap",
fn: "onNewButtonTap"
}
We defined the List’s disclose handler in a similar fashion. The delegate points to the List’s itemId, and fn is the onNotesListDisclose function:
{
delegate: "#notesList",
event: "disclose",
fn: "onNotesListDisclose"
}
Configuring the Note Editor
Now we are going to move on to the NoteEditor View, where we will replace the initialize function with the config’s items and listeners properties:
Ext.define("NotesApp.view.NoteEditor", {
extend: "Ext.form.Panel",
requires: "Ext.form.FieldSet",
alias: "widget.noteeditorview",
config: {
scrollable: 'vertical',
items: [
{
xtype: "toolbar",
docked: "top",
title: "Edit Note",
items: [
{
xtype: "button",
ui: "back",
text: "Home",
itemId: "backButton"
},
{ xtype: "spacer" },
{
xtype: "button",
ui: "action",
text: "Save",
itemId: "saveButton"
}
]
},
{
xtype: "toolbar",
docked: "bottom",
items: [
{
xtype: "button",
iconCls: "trash",
iconMask: true,
itemId: "deleteButton"
}
]
},
{ xtype: "fieldset",
items: [
{
xtype: 'textfield',
name: 'title',
label: 'Title',
required: true
},
{
xtype: 'textareafield',
name: 'narrative',
label: 'Narrative'
}
]
}
],
listeners: [
{
delegate: "#backButton",
event: "tap",
fn: "onBackButtonTap"
},
{
delegate: "#saveButton",
event: "tap",
fn: "onSaveButtonTap"
},
{
delegate: "#deleteButton",
event: "tap",
fn: "onDeleteButtonTap"
}
]
},
onSaveButtonTap: function () {
console.log("saveNoteCommand");
this.fireEvent("saveNoteCommand", this);
},
onDeleteButtonTap: function () {
console.log("deleteNoteCommand");
this.fireEvent("deleteNoteCommand", this);
},
onBackButtonTap: function () {
console.log("backToHomeCommand");
this.fireEvent("backToHomeCommand", this);
}
});
We are following the same approach we used to configure the NotesList View. This time, we need listeners for the Back, Save and Delete buttons:
listeners: [
{
delegate: "#backButton",
event: "tap",
fn: "onBackButtonTap"
},
{
delegate: "#saveButton",
event: "tap",
fn: "onSaveButtonTap"
},
{
delegate: "#deleteButton",
event: "tap",
fn: "onDeleteButtonTap"
}
]
The onBackButtonTap, onSaveButtonTap, and onDeleteButtonTap function remain unchanged.
Adding View Instances to the Application
In the app.js file, we are going to instantiate both Views as follows:
Ext.application({
name: "NotesApp",
models: ["Note"],
stores: ["Notes"],
controllers: ["Notes"],
views: ["NotesList", "NoteEditor"],
launch: function () {
var notesListView = {
xtype: "noteslistview"
};
var noteEditorView = {
xtype: "noteeditorview"
};
Ext.Viewport.add([notesListView, noteEditorView]);
}
});
Modifying the Controller
The Controller remains unchanged, with the exception of the Views aliases, which we have changed in the chapter of the tutorial:
Ext.define("NotesApp.controller.Notes", {
extend: "Ext.app.Controller",
config: {
refs: {
// We're going to lookup our views by alias.
notesListView: "noteslistview",
noteEditorView: "noteeditorview",
notesList: "#notesList"
},
control: {
notesListView: {
// The commands fired by the notes list container.
newNoteCommand: "onNewNoteCommand",
editNoteCommand: "onEditNoteCommand"
},
noteEditorView: {
// The commands fired by the note editor.
saveNoteCommand: "onSaveNoteCommand",
deleteNoteCommand: "onDeleteNoteCommand",
backToHomeCommand: "onBackToHomeCommand"
}
}
},
// Transitions
slideLeftTransition: { type: 'slide', direction: 'left' },
slideRightTransition: { type: 'slide', direction: 'right' },
// Helper functions
getRandomInt: function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
activateNoteEditor: function (record) {
var noteEditorView = this.getNoteEditorView();
noteEditorView.setRecord(record); // load() is deprecated.
Ext.Viewport.animateActiveItem(noteEditorView, this.slideLeftTransition);
},
activateNotesList: function () {
Ext.Viewport.animateActiveItem(this.getNotesListView(), this.slideRightTransition);
},
// Commands.
onNewNoteCommand: function () {
console.log("onNewNoteCommand");
var now = new Date();
var noteId = (now.getTime()).toString() + (this.getRandomInt(0, 100)).toString();
var newNote = Ext.create("NotesApp.model.Note", {
id: noteId,
dateCreated: now,
title: "",
narrative: ""
});
this.activateNoteEditor(newNote);
},
onEditNoteCommand: function (list, record) {
console.log("onEditNoteCommand");
this.activateNoteEditor(record);
},
onSaveNoteCommand: function () {
console.log("onSaveNoteCommand");
var noteEditorView = this.getNoteEditorView();
var currentNote = noteEditorView.getRecord();
var newValues = noteEditorView.getValues();
// Update the current note's fields with form values.
currentNote.set("title", newValues.title);
currentNote.set("narrative", newValues.narrative);
var errors = currentNote.validate();
if (!errors.isValid()) {
Ext.Msg.alert('Wait!', errors.getByField("title")[0].getMessage(), Ext.emptyFn);
currentNote.reject();
return;
}
var notesStore = Ext.getStore("Notes");
if (null == notesStore.findRecord('id', currentNote.data.id)) {
notesStore.add(currentNote);
}
notesStore.sync();
notesStore.sort([{ property: 'dateCreated', direction: 'DESC'}]);
this.activateNotesList();
},
onDeleteNoteCommand: function () {
console.log("onDeleteNoteCommand");
var noteEditorView = this.getNoteEditorView();
var currentNote = noteEditorView.getRecord();
var notesStore = Ext.getStore("Notes");
notesStore.remove(currentNote);
notesStore.sync();
this.activateNotesList();
},
onBackToHomeCommand: function () {
console.log("onBackToHomeCommand");
this.activateNotesList();
},
// Base Class functions.
launch: function () {
this.callParent(arguments);
var notesStore = Ext.getStore("Notes");
notesStore.load();
console.log("launch");
},
init: function () {
this.callParent(arguments);
console.log("init");
}
});
Summary
We just created a version of the Notes Application where, instead of the initialize function, we exclusively used config objects to configure each of the application’s Views. In the process, we learned how to create event listeners for components defined using config objects.
At this point, we have accomplished our goals for this application. I hope the insights you gained in this Sencha Touch tutorial will help you create great mobile applications.
Downloads
Download the source code for this article: NotesApp-ST2-Part5.zip
The Entire Series
- How to Create a Sencha Touch 2 App, Part 1
- How to Create a Sencha Touch 2 App, Part 2
- How to Create a Sencha Touch 2 App, Part 3
- How to Create a Sencha Touch 2 App, Part 4
- How to Create a Sencha Touch 2 App, Part 5
Want To Learn More?
My Sencha Touch books will teach you how to create an application from scratch.
What Sencha Touch Topics Would You Like Me To Write About?
I’d like to help you learn Sencha Touch better and faster, but I need you to let me know what subjects you are curious about, or what topics you are struggling with.
Please send me your questions or suggestions for future posts at miamicoder[AT]gmail.com.


Hi,
Wonderful post Jorge!!!
I used to do this method earlier, so finally seeing the code in this way is really good.
Hey, I had another doubt about Sencha Searchfield…It is by default with rounded corners, and they say that it is because they have used HTML5 search. Is there any way it can be altered to make it rectangular. I have made extensive changes in the sass and css but to no success.. Kindly help if you can..
Thanks&Regards
Thanks! Interesting question. I’ve never tried to change the look of the search field in ST. Let me research the topic.
Hi George,
Writing to tell you that by doing $include-border-radius: false in the _variables.scss I was able to achieve square corners, but it has turned off all the radius property to 0 in all the components. Luckily I have no rounded components to develop!!!
..but u find any other way, do tell us whenever you delve for this topic..
Thanks & Regards
how can i use this demo.i mean i download NotesApp-ST2-Part5.zip.extract it in my tomacat webapp,but i can not see the result. Is there anything wrong?
Andy, open the app in Google Chrome and check out the JavaScript console. Are you missing the Sencha Touch files?
hi,
this way using config object looks straightforward. it is more readable.
I’m wondering where you get these properties, like event: tap, delegate: button.
which i research sencha docs and haven’t found.
For a reference on listeners, check the Ext.mixin.Observable docs: http://docs.sencha.com/touch/2-0/#!/api/Ext.mixin.Observable-method-addListener
¡Error!
Hi, good Example, thanks, i have one question, i run your example app, but when i delete some item list, and reload the page , an error rise in the browser:
Uncaught TypeError: Cannot read property ‘isModel’ of undefined
What’s going on?
Thanks
Check the syntax or the way you declare/use isModel i had similar issues vith case sensitive (for example) viewpoint.isValid and changed it with Viewpoint.isValid
HTH
Hi Jorge !
Great Great explanations in this tutorial which is guiding a lot the beginner i’m right now! I also bought your ebook and will follow it again as i’m reviewing the current tutorials.
I’m running into few issues like my list is not showing up, even if i create a new note and save it;also typos in the view notesList with \" syntax
I just changed \" to \"’ and works;now on testing
Thank you. The syntax highlighter plugin I use for my posts is causing the issues with the quotes.
Hi Jorge,
Sir is it possible to launch Email and phone without using phonegap in sencha touch ?
Yes, use the mailto and tel hrefs. For example href=”tel:2125551212″.
Hi George,
I just wanted to ask if u knew how to open a new window in safari on a button click…
windows.open() is not working, even with a blank attribute..
Thanks & Regards,
Why do you think you need to open a new browser window?
Hi Jorge,
Actually I need to open a pdf file in my iPad application. The problem with using iFrames is that it renders the pdf open but it is not scrollable. So I had to try to open it on the native browser.
I am not able to get the window opened through sencha touch commands.
Sorry for the late post, too much work this side..
Hi jorge,
Thanks for the Wonderful post i really liked it.
can you please provide an MVC tutorial on Carousel where images come from Web service
Thanks
Ram
You’re welcome Ram. Interesting idea. I will try to write about this as soon as possible.
Hi Jorge,
Is it possible to write an article with a small example on using JsonP with Sencha Touch2 . There are lot of people (including me) facing issues using Sencha Touch2 with JsonP.
Thanks,
Sathish G.
Sure, Sathish. I will try to post an example as soon as possible.
Jorge,
By far the best Touch 2 example I have seen. Got a question on using the MVC paradigm.
I understand using controllers to replace placing events (such as TAP) under each component, but is there a good reason why I should not just call a function from the event handler of the component. Both methods prevent having to write the same code. I kind of like knowing that the button’s TAP event is calling my PostDataToServer() function. Also I would believe that referencing a function defined at the application level would be found faster then having the controller locate the button with the #myButton ItemId. I understand that I can define multiple controllers, but for most apps this seems like a bit of overkill. I want to use MVC, but it has to make sense. Any examples you can provide to show why MVC is the better way to go would be very appreciated..
Thank you. I understand what you are saying, and I think that for small apps where the requirements will never change, and where there’s sole developer or a very small team, it might feel like you have to write more code and do not gain much by moving business logic out of the views. However, requirements will always change, in particular in larger apps. Teams are not always of one person. In situations like those, you don’t want your views invoking BL functions directly. I would argue that this is also true when you are a sole developer. You don’t need your views to know how the app’s BL works, because if you change the way the BL works, you will need to change the views. This is bad specially if you have to change the app after months of being in production, when you’ve already forgotten how many views call a given function, for example. There are more benefits to the MVC implementation in ST2, such as auto setters and getters, but I won’t go in detail about them here.
Thank you for your reply. I agree with what you said about BL not being in the VIEW. When I code an event for a component in most cases, My event code has only 1 line which is a call to a function I define at the app level. I usually pass THIS and the component (maybe a Record Object if applicable) as params to my function. So I am in a way keeping the business logic out of the view. It just seems to me that converting an event to a controller action is a lot more overhead for the JS engine. Also I like knowing while I am viewing my “views” in code what functions the various events I or others have created are calling. With PURE MVC you lose this visibility and have to search thru your controller functions to see what components and events a function is referenced to. If I am missing the point, I would love an example. I do not want to continue coding in this style if there is a better way, I just don’t see it (yet!). By the way. I am using Sencha Architect 2 (Paid Version). It has a lot going for it, but really miss using PHP storm (Code Completion spoils you).
Just finish watching a video with Ed Spencer (Sencacon 2011) about MVC and got a lot of questions answered. BUT !!!! it would seem that unless you have a very complex app with lots of views and events to manage, my original assumption seems better IMHO. The amount of code you need to write and the method that MVC uses to link an event to a specific function (Controller Action) requires more effort (code) than just calling a function directly from a component listener events. Maybe I am old school (Hard to teach old dogs new trick) but for small to medium size apps it seems a bit overkill. Since you have to define an ID: value to use Controller actions, It would appear they (Framework) are doing a getCmp() behind the scenes.
I do really appreciate the time an effort you have spent on your tutorial and hope you continue to publish additional examples of what can be done with Sencha touch.
I have high hopes that Sencha Architect will at some point allow the addition of third party components as I have discovered there are a few that I would like to use. Sencha is much harder to learn then JQuery, but I believe in the long run it will worth it.
Cheers Billy B
Hi jorge,
I have a global toolbar View and a controller for that and i am using this view as xclass in all other views and these views have their own controllers, So now my problem is i have only one back button in global toolbar, So how can i implement the back Logic Please help me solve this problem.
Thanks
Ram
One way to do what you need is to, in the global controller, have a reference to each of the views that will need to change state when the back button is tapped. Another approach would be to have the global controller send a message to each of the child controllers, asking them to handle the “back” logic.
Hi Jorge,
Thanks for ur reply i have only one back button in global controller how can i get a reference that in which view i am and how can i call the corresponding child controller ? Please help me to solve this problem.
Thanks
Ram
You get references the same way you get a reference from the child controller. You can then fire a “navigateBack” event from the global controller, and have the child controllers listen to it.
Thanks got it Solved using routes
Great. You can also listen to the event that occurs when a view becomes visible.
Hi Jorge,
Is there any other way adding views to Viewport the views adding to viewport in your case
Ext.Viewport.add([home,secondView,thirdView,fourthView]);
Is calling all the initialize functions of all views i want to call the initialize functions only when i move to their perticular views.
Thanks
Ram
I’m a designer learning JS and have settled on Sencha’s Architect 2 as the best environment for developing UX designs. I left Flash Catalyst after Adobe abandoned the product. HTML 5 will be around for a while and is a worthy platform for beginners like myself to learn. The drag and drop interface and configuration panel, exposing objects properties I think will draw many like myself interested in creative control of the entire experience. How about developing a series of tutorials geared towards beginners using Architect 2, focusing on the UX.
Thanks!
Thank you Charles. Architect is a very interesting tool. I will try to write about it as soon as I can. When people ask about it, I always recommend that they start by learning how Sencha Touch or Ext JS work. Only then can they take full advantage of Architect.
Really awesome post. It’s hard to find good articles on 2.0. I’m just starting with the sencha touch.
I was wondering. How would it work if I wanted 2 controllers instead of 1.
A controller for the NoteList and another for the NoteEditor.
I’m expecting that the app.js, will only have initially loaded the controller of NoteList since it doesn’t need to load the NoteEditor controller.
Would that be possible?
Thanks,
Thank you, Paul. Yes, it’s possible to have more than one controller. For small apps like this one, I usually start with one. As features are added to the app, I check to see if it makes more sense to distribute the responsibilities across multiple controllers.
Would you be able to write an article on this subject, like a more real world example with multiple controllers each controlling a specific view? I’m really curious to see how this would work. I tried myself and failed miserably. I’m at a point where I don’t really know how to load the second controller. For example, your notes app. You have the NoteList and the Notes controller. When user tap on an item it shows the NoteEditor. From there how could I load the NoteEditor controller? A way to make it work would be to have it in the app.js …. but that wouldn’t make much sense does it? Since it is only needed when the NoteEditor is visible. Loading the NoteEditor controller at the very beginning when it is not needed could cause a performance issue I would assume.
Thanks,
Can’t never lunch this tut. at all! Even I supplied all the required files not packed with this .zip as below. Could you tell me how to run this tut.?
What error message do you see in Chrome’s console?
I see nothing, but btw, I got it set up with PhoneGap, it works now. Thx.
OK. Glad you figured it out.
Gr8 post , very helpful indeed!
Any idea how to implement the autocomplete functionality in Sencha Touch 2 ? . I’m stuck with that for a while. Help will be very much appriciated.
Thanks in advance
As per sencha doc its a bad practice to define event listeners and handler in the view file when doing Ext.define. Any input on this?
Please post the link to the docs.
http://docs.sencha.com/touch/2-0/#!/api/Ext.Panel-cfg-listeners
http://screencast.com/t/AhX5MdD0
I just wanted to see what you had to say about this topic. The concern is that we added the listener when doing a class define and not when we created an instance. Maybe you can shed more light in this area. Thx
Thanks. First, I’d like the documentation to explain why it’s bad practice. That will help more than simply saying it is bad practice. Second, I think this refers to listeners that are intended to be instance-specific. In other words, listeners to public events of a class. If that’s the case, I agree. If you want to listen to events pubished a class, you should define the listeners when the instance is created, not when the class is defined.
However, in the case of my tutorial, the listeners and the handlers you refer to are internal to the class. They simply serve to transform events in internal components of the class into public events of the class. Notice that the listeners for these public events, which I define in the controller, could be said to follow the “best” practice, as they apply to an instance of the class that fires the events.
thanks for the reply
need help understanding itemID. Is it just like having an attribute like name and then searching it like
container.query([name="bla"]) or does itemId add any other features?
The itemId config of a component, not to be confused with the id, is an index into the items collection of the Container that hosts such component. Therefore what you say is valid and useful to quickly find child components of any container within the container’s scope. Components in different containers can have the same id, which is useful when you create multiple instances of the same class, for example.
i see. that makes sense.. so rather than using a numeric index in the items array we are looking them up by a friendlier string. thx
Hi Jorge,
This is a wonderful article. If you could write about production deployment processes, like using the cache manifest and micro-loader, it would be great. Looking forward to your posts. Thank you.
Thanks, Shiva. I will try to address your request as soon as possible.
Nice Article for the beginners …Thanks
You’re welcome! Any topics you’d like to learn in detail?
Jorge,
This is a very good tutorial. However, I will like you to write about using a Tap event on an Image which calls another panel.
Hey Jorge..thanx for the post…man i have a list of items with a disclosure on each list…..and what i want is to pass the id of an item on disclosure to the server so that i use the id on the sever side to query the database…..but i don’t know how to do it…..how can i post the id on itemDisclosure
Thanks for the nice tutorial!
Just a thought, if you want the browser (and Android) Back buttons to work, routes are the way to go. At the top of the Notes controller, add the following:
routes: {
”: ‘activateNotesList’,
‘notesEditorView’: ‘showNoteEditorView’
}
The empty route specifies which method of the controller will be called when you load index.html without an anchor (e.g. when you launch the app); the “notesEditorView” route specifies which method will be called when you load the “notesEditorView” anchor (e.g. when you call redirectTo() to go to another view).
After configuring the routes, replace the activateNoteEditor() method with the following 2 methods:
activateNoteEditor: function(record) {
var noteEditorView = this.getNoteEditorView();
noteEditorView.setRecord(record);
this.getApplication().redirectTo(‘notesEditorView’);
},
showNoteEditorView: function() {
Ext.Viewport.animateActiveItem(noteEditorView, this.slideLeftTransition);
}
In activateNoteEditor(), you get a reference to the editor view and set its record. But instead of just showing the view, you call redirectTo(), which will redirect the browser to the anchor you specify. Since you’ve configured a route for that anchor, the showNoteEditorView() handler is then called, and that’s where you actually show the view in the UI. The difference can be observed in your browser’s address bar. You’re now adding to the browser history.
The last step is to replace all calls to this.activateNotesList() with calls to history.back(). When you press the Back, Save or Delete buttons, history.back() will be called. The empty-anchor route is configured to call activateNotesList(), which shows the list view. This method will also be called if you press the browser or Android Back button.
If you have a complex app with many depth levels and you want to efficiently support the Android Back button, this is a good way to go.
Hope this helps!
Very nice. Thank you, Alex!
Hello Jorge,
I have the following error:
Uncaught Error: Ext.setup has already been called before sencha-touch.js:8890
Ext.setup sencha-touch.js:8890
Ext.apply.application sencha-touch.js:9219
(anonymous function) app.js:1
app.js:1 is Ext.application({
Hope for any hint. Thank you.
I found it
In the index.html file, I have had this line .
After deleting the line it is ok.
I wouldn’t have learnt #sencha this beautifully if your tutorial wouldn’t have been there, this is 100x much better than tutorials on their website. You Rock!! \m/
Thank you!
Hi,
In many cases you have used “delegate” in the config. Can you point out where in the documentation “delegate” is defined? I am not able to find reference to it.
Thanks
Check here: http://docs.sencha.com/touch/2-0/#!/api/Ext.mixin.Observable-method-addListener
nice tuts,,,,,,,, i read it many times
try to understand concept of MVC, i had a little bit concern in calling MVC, coz it little bit different with EXT JS 2.2 i’ve learn, just like learn something new here ,,,,,,,
wish i have your brain in me,,,,heeee
great job
tx
Jeorge i am very thankful for giving you this kind of tutorial. You are a great person and a generous one and a whole heart love for giving a knowledge for the other person who wants to learn this mobile application. People who loves to make mobile app and continuing to learn will never forget you how you help them on how they learn from the beginning. I hope that you will not change and thank you once again.
Ciao Jeorge, great tutorial, i want buy your book, but before i want ask you if it needs an update to sencha 2.1, the examples of your book work with st2.1?
grazie
Hi Vf. Yes, the examples will work with 2.1. Thank you for your support!
Hi Jorge,
I have written an email to you earlier. Nice tutorials you have got here on ST2.
How about getting your ebook?
Thanks.
Hi Jorge,
Nice tutorial and it is very helpful for beginners like me.
I want to add container within another container programmatically first time it works great next time onwards it is not working any suggestion to resolve the issue.
Post your code, please.
Uncaught TypeError: Object 2013-04-09T00:18:58+08:00 has no method ‘getFullYear’
touch-2.2.0
This is not enough information to help you. Please post more of your code.
Hi Jorge,
You made excellent tutorials.
I download the code and run on my PC and everything work like charm.
But when I run the application on iPhone 4 or iPhone 5 using Google Chrome, there is no bottom bar in ‘Edit note’ screen.
I have made no changes to the code.
Can take a look and tell me what causes it ?
Thank you very much.
Jorge,
I’ve gone through your eBook and tried to run the production code, when I got this error:
XMLHttpRequest cannot load file:///MyNotes/build/MyNotes/production/app.json?1368371697903. Cross origin requests are only supported for HTTP.
Any ideas as to why?
I also tried to install on android device. It installed and the main screen appears. The message No Notes appears, but the New button doesn’t work. Have you seen this before?
Thanks,
Ron
This is happening because you are accessing the app through the file system, instead of through your local web server. The uri you type on your browser should start with http, something like this: http://mynotes …, where mynotes is the virtual folder where your app resides.