SC2.0 & TemplateViews, some short thoughts
It’s been a really long time since I’ve posted any tips, sorry. Mostly because I moved onto other projects & wasn’t using SproutCore for awhile. I started using it again a month or two ago, so onto some tips.. but first I just wanted to comment on the SC 2.0 bit… I see a lot of people asking the same questions over and over “What do I use” and worse, people trying to jump on the new hotness then finding a big empty void of support & help.
Lastly, I’ll preface this with a disclaimer before I get started. This is all purely my opinion.
The only applications I’m aware of that have successfully been shipped and are well known SproutCore applications, are built on SC 1.6. (Including MobileMe) None of these applications use “TemplateViews” and none of them use SC2.0. Why do I point that out? People want to jump on the new hotness, but, none of that stuff is proven, or fully developed yet. If you want a platform to build applications on, the only one that CURRENTLY EXISTS, is SC1.6 (ignoring templateviews)
Support, examples, anything, it all currently is built on SC1.6 and pre that. Blog posts outside of the main sproutcore.com website about template views, or how to do XYZ in SC2.0? Not likely to arrive for awhile.
There is nothing *there* yet. TemplateViews don’t fully integrate well with the other parts that must be used, because templateviews aren’t fully featured yet. SC2.0 isn’t fully featured yet, and more importantly, there aren’t any apps, and likely very few developers actually shipping apps on it.
Having said that, SC2.0 is clearly the direction one branch of SproutCore seems to be going, so *eventually* I imagine it *will* be fully featured, it will have a widget library, controls, and full integration, including a bunch of people blogging about how to use it, with examples, and get lots of well known apps that were written in SC2.0.
If you want to develop a SproutCore application, need support and help, you are better off using SC1.6. I mention not using templateviews because they aren’t fully featured, and you are going to have to go use ‘non templateview’ features at some point for your app, which is when you are going to run into all the rough edges, the stuff that hasn’t been worked on for years (SC1.6 and pre), the stuff that doesn’t have any apps built on it (templateviews , handlebars, and sc2.0) and thats going to slow you down, cause you pain, and make you not like SproutCore.
Now, I probably upset some people, I’m sorry for that. I think SC2.0 will be great, but I think its really bad to distract people with its existence when its functionally unusable for practically anyone’s serious application building needs. One more thing to note, is that MobileMe clearly shipped some really successful applications, on both Mobile and Desktop mind you, using SC1.6. Clearly its possible to build great applications with SC1.6, and you don’t need to rush to the new hotness just to make great apps with SproutCore. SC2.0 clearly intends to make developing those applications easier & better than SC1.6, but again, its not done!
I hope that this entire post is totally invalid in 6 months once SC2.0 has all the same resources SC1.6 has behind it, a community of people that have successfully shipped apps, understand all its parts, and it actually has a fully fleshed out set of tools to help you build those apps. Make no mistake, SC2.0 is clearly the intended future, but, at this point, its still IN the future.
So, Hold your horses… evaluate if you REALLY need to use TemplateViews & SC2.0, or if you actually just need to develop a great web app, because if you want to do the latter, its probably a safer bet (and less painful road) to use SC1.6(without TV) .
Quick “dynamic” layout!
You can adjust a views position at any time by simply calling this.set(‘layout’,{top: x, bottom: y, height: z, width: v} ); instant view movement!
I use this fairly often when I get data back from the server, or want to place a view in a specific position based on user interaction (like a click, or a mouse in/hover action)
A simple progress indicator
I was looking for a way to do a progress indicator, and did find this helpful tutorial, http://wiki.sproutcore.com/Tutorials+-+Loading+Indicator but its based off records returning their state, which isn’t very helpful if you aren’t interacting with records yet.
There is also an easy way to do it in jQuery, found here which uses .ajaxStart & .ajaxStop to add/remove a DIV.
Lastly, before I get started, there is a http://docs.sproutcore.com/symbols/SC.ProgressView.html#constructor which is a bar that just animates until you ask it to stop. (for indeterminate).
Anyway, I wanted basically what I found in jQuery, but to do it in sproutcore instead.
First things first, we make a new view to extend
MyApp.ProgressIndicatorView = SC.View.extend(SC.ContentDisplay, {
Then we override render context
classNames: [‘progressIndicator’],
render: function(context, firstTime) {
context = context.begin().addClass(‘indicatorBusy’); //< div class=”indicatorBusy”>
context = context.begin(‘img’).attr(‘src’,’/images/my-loader.gif’).attr(‘width’,”16”).attr(‘height’,”16”).end(); //<img src = “/images/my-loader.gif”></img>
context = context.begin(‘p’).addClass(‘loadingLabel’);// <p class=”loadingLabel”>
context = context.push(’ Fetching Records…’);
context = context.end(); //</p>
context = context.end(); // </div>
sc_super();
}
});
Ha already almost done! I like to write the html I want to create first, in comments, then add the context data in front of it, so I know exactly what I want to create before I deal with doing it in the render context.
Next we need to add our view, place it, and determine how to show it. I’m doing this in main_page.js
progressIndicator: MyApp.ProgressIndicatorView.design({
layout: { bottom: 10, right: 5, height: 20, width: 140 },
activeRequestsBinding: ‘MyApp.activeRequests’,
isVisible: function () {
return this.get(‘activeRequests’) > 0 ;
}.property(‘activeRequests’)
}),
What we are doing here is binding to a property in core.js called “activeRequests” that starts at 0. Whenever the value is greater than 0, the view will toggle its visibility on, and you’ll see the spinner & text appear.
Its a pretty basic example, you’ll need to remember to increment your activeRequests when you make an XHR, and decrement it when you are notified of the requests return. Ideally you’d handle that in a controller, and all of this assumes you aren’t just simply using the datastore to begin with (in which case you’d look at the record status)
Also there is a handy site for generating loader images, http://ajaxload.info/ .
Thanks to Alex Iskander for the tips & help.
Debugging Tips! Part 1
I have had a heck of a time getting up to speed with regards to debugging my sproutcore app. Hopefully you are already aware of Firebug & Safari Web Inspector . Sometimes I’m not able to step through in the debugger, for various reasons.
(Quick hint! You can’t leave “debugger;” statements in and do an sc-build! It will fail.
Now, once you are in the console there are a couple useful tools accessible to you. I know its incredibly unhelpful when you say
var data = MyApp.store.find(MyApp.MyRecord)
[ > Object ]
Oh man, when I see [ Object ] I want to scream/cry, I’m used to cocoa description methods, which tell me so much more about the object. I know its an object, be more helpful! ;)
- Try data.toString() to see what it looks like as a string
- Check the length, data.get(‘length’), this can be helpful in letting you know if any data is even present.
- Alternatively there is data.toArray() to see the object as an array
- data.readAttribute(‘someProperty’)
Use JSLint! This tool has saved me so many headaches just on save & test alone.
This last one, I’m embarrassed to admit, has caused me two serious headaches for far longer than they should have, and the fixes (partially) were so. simple! I cringe thinking about these.
Remember! Your! Case! If you are like me and used to camelCase, make sure you have not done DoubleCase in one place, and camelCase in another.
The final one is make sure you fully read your references. I stared at code for hours before someone (Charles) pointed out that MyAppB.myController.arrangedObjects and MyAppE.myController.arrangedObjects were not the same thing. I was glancing at the bindings, thinking yeah I’m binding to the controller arrangedObjects thats fine, what else could be wrong… JS/Sproutcore won’t care that you are binding to MyAppB when you are in MyAppE and MyAppB doesn’t even exist. It can and will let you do this.
Big thanks to #sproutcore (Alex, Colin, Peter, Devin, etgryphon) and Charles Jolley for their help in debugging my numerous (and sometimes very simple) issues. Thanks for your patience gentlemen.
You ended up using context.begin… but its missing add’X’.
You searched and searched for how to do something, and the only thing you could find were some tutorials about going into the context & pushing values. Fantastic.
You saw that you can
context = context.begin(‘table’).addClass(‘myCSSClass’);
And hey that was pretty cool, you know some CSS and how to use a class. But you also need to add an id and scope. Hmm. There is no “addScope” or “addID”. What to do what to do…
context = context.begin(‘table’).attr(‘id’,’my ID’).attr(‘scope’,’col’);
Viola! Now you’ll see <table id=’my ID’ scope= ‘col’ > in the HTML. Carry on…
Thanks #sproutcore for that one.
Getting data into child-child views without the controller
Hopefully you’ve seen the composite view tutorial,
http://www.itsgotwhatplantscrave.com/2009/07/29/composite-views/
It’s an excellent example of extending a view to save yourself from duplicating code. To give an example of how I used it, I had a particular “table view” that consisted of a lot of heavy styling. Which involved of course divs and classNames.
In the end, I wanted to reuse this “table view” in several difference places (3, to be exact). After following Evins guide, I was set; almost.
Say your table has a header title, and its the third child view down. When you duplicate this table view, you’ll probably want a unique title for every table header. You can create a property on the parent that will be easily accessible to your instance of this view ( SC.myView.design({}) ) to directly pass it a value. Its basic, I know, but hey, I’m new!
MyApp.MyCustomView = SC.View.extend({
headerTitle: ”,
createChildViews: function(){
var childViews = [],view;
view = this.createChildView (
SC.View.design ({
classNames: ‘contentCalloutHeader’,
layout: { left: 17, top: 40, width: 50, height:20},
childViews: ‘calloutTextHeader’.w(),
calloutTextHeader: SC.LabelView.design ({
classNames: ‘calloutTextHeader’,
layout: { left: 17, top: 0, width:20, height: 10},
valueBinding: ‘.parentView.parentView.headerTitle’
})
}),
Now, over in your design, you can simply set a value
someView: MyApp.MyCustomView.design({
layout: {top: 30,left: 20, height: 200, width: 200 },
headerTitle:’A Unique String’
And there you have it, setting a property on a parent to get it down into a child view.
I realize this is practically what Evin was doing, except with bindings all around. The thing for me, about bindings, is I don’t really know what they are doing, so I’m never really sure what I can get away with doing. I was happy to learn I could just set a text value, and it would be picked up far down in the child child views. For me, a lot of the learning process is just discovering what I can do in the language.
Ideally, I think you’d want to have a controller have a property, and just bind to that, this way your controller is supplying data to your view, instead of your hard coding it in. Also when using .parentView be aware that views can be added & removed, so *parentView.headerTitle may help you in that case. Especially inside a scrollview.
You can read more about chained & relative bindings here
hawleyw asked: Is there a way to change the default copyright notice that sc-gen puts in the generated .js files?
Its painful, and will probably take longer to fix on the generator side than it would to just find & replace in BBEdit or textmate, but here is what you’d do.
- Download Sproutcore abbot
- Head to the file you wanted to modify in the “gen” directory
- /abbot/gen/app/templates/apps/@target_name@
- nano core.js
- Modify the header file
- Ctrl +X, Y, Enter (Exit & Save)
- Now when you sc-gen a new app, the core.js header file should reflect your changes.
Yes, unfortunately it looks like you’d have to do it for each file and each generator. The above example just modifies the output for a new app and just core.js. You also have to use the abbot generator, so you’d have to do /abbot/bin/sc-gen, as your local sc-gen probably doesn’t map to abbots.
Thanks to Alex for the direction on solving this
Integrating with other frameworks (flot, django, raphael)
Since it was relevant to me, I thought I’d post a few links for getting charting & data backends integrated with Flot. There are a couple easy hits on google. I’ve also heard someone! is working on native sproutcore charting. He is a very busy someone however, but I’m sure we’ll see something in the coming months.
Flot
http://github.com/imxiaobo/iamxiaobo/tree/master/flot-integration
http://colincodes.tumblr.com/post/512234561/sproutcore-and-flot
http://sproutcoreplayground.com/examples/flot
Django
http://github.com/sproutcoreisyournewbicycle/sproutcore-django
Raphael
Where does it all come from?
I don’t want people to get the wrong impression; I’m not this smart. All of this knowledge is merely what I condense down from the very smart and very helpful people in #sproutcore on freenode.net. Its also not always verbatim what they say, its how I see it through my eyes, as I’ve been learning sproutcore. And of course, its perfectly liable to be “well, thats not quite right…” For me, if it works when I run the app, its right enough for me ;)
I always try to search on the web for questions like these, and inevitably I was not finding answers. Instead of having people like charles & alex & evin etc constantly answer the same questions over & over, I figured maybe I should do my part (what little I can) to document the answers to the questions I’ve had, or the questions I’ve seen asked by others that where answers will be lost in the logs of a 1 to 1 Q & A.
Also, many of these questions will be one-offs, some of what tends to be easier to learn in individual questions, and aren’t really worth a full blown tutorial.
Using your fixtures in sc-build
Alright, so you read through the datastore tutorial, it told you all about fixtures, and that it was a stop gap for hooking up to a real data source. It even gave you a neat shortcut to fall back on fixtures.
// in main.js:
MyApp.main = function() {
// switch to fixtures if #fixtures in URL
if (window.location.hash.toString().match(‘fixtures’)) {
MyApp.store.from(SC.Record.fixtures);
}
…
}
But! It forgot to tell you how to use fixtures when you don’t have a backend setup yet, but still need to deploy somewhere for demo purposes!
Buildfile to the rescue! Add “:load_fixtures => true” into your buildfile & deploy, voila! Fixture data on the live server.
config :all, :required => :sproutcore, :load_fixtures => true
Page 1 of 2