Nice screencast, thanks. I wonder if the rjs stuff is still in rails 3? I'm using it a lot, it simplifies working with javascript quite a bit. For example by making helpers that output js via the update_page function. Is that still supported in rails 3?
Hello Ryan, like usually, thanks for your work. :)
In the javascript code, why do you use "return false;" instead of "event.preventDefault();" ?
And i have a suggestion for a unobstrusive links with actions methods : the idea is to use the noscript tag to provide a button_to if scripts are disabled and link_to in normal cases.
Of course, the other way is to use only buttons for actions, with nice styles. :)
Thanks, this screencast is much appreciated. I am also wondering about RJS and Rails 3? I have used RJS with much joy in that past and I am hoping that it would still be supported in Rails 3.
I've made a simple init generator which will download the latest rails.js (jquery) and doing some other stuff: http://github.com/mendelbenjamin/rhj_init
What happens if the user is not using a HTML 5 capable browser? I imagine it will be quite a few years until you can assume that all your users have HTML 5.
@Nico, @Willem - rails 3 still contains RJS via http://github.com/rails/prototype_legacy_helper and only available for prototype, however nothing prevents you from creating a js.erb view containing the javascript you would like executed
@Romain - event.preventDefault only prevents the browsers default action, returning false stops the event from propogating (including other handlers)
@Martin - the data-* attributes function in all major browsers, however it will not validate as custom attributes are not part of the HTML spec until HTML5
@Steve: So to have a rails helper that outputs js I could e.g. render a js.erb partial in a helper? Is that what you mean? Anyway rjs had some nice functionality. Abstracting away from the actual js using ruby is nice. I liked that...
I still maintain that there should be a "delete" GET action by default similar to how we have "edit" for update. This would allow everything to work without javascript, is this not the whole point in unobtrusive javascript.
I wrote an article back in 2006 outlining why this is a good idea http://thelucid.com/2006/07/26/simply-restful-the-missing-action/
@Nico, Yes, you can render a js.erb partial if you need to generate JavaScript in a helper.
I rarely find the need to use RJS anymore. It worked well back when I could not stand JavaScript, but jQuery and other frameworks make JavaScript much nicer to work with.
Simple things like JavaScript "if" conditions are very ugly to do with RJS. I encourage you to learn to use JavaScript directly and it will be more flexible.
@Romain, in what way is "return false" dangerous? It basically tells the browser to not follow the "href" part of the link.
@Jamie, I can understand both sides here. In some ways I would like to see a "delete" action be there by default, but the implementation of the confirmation page would be a lot of duplication across controllers.
Certainly Rails could handle the confirmation page behind the scenes but I think that kind of implementation fits better in a plugin. I hope with Rails 3's approach to plugins it will be much nicer to write a plugin which extends "resources" in routes and adds a delete action and view.
I'll post this on your blog post as well which is probably the best place to continue the discussion.
Thanks for the cast Ryan. I know this comment won't be popular, but I have very mixed feelings about UJS.
I've worked on big ajax-heavy production projects with both prototype helpers and UJS JQuery, and the UJS projects inevitably ended up more obtrusive and convoluted. Mostly because of the sheer quantity of javascript files needed, as well as programatically generating javascript in rails or C# (gross) once you get into more complex tasks.
I'll still give this a try but remain somewhat skeptical.
Was also wondering if render :update still exists unaltered on the controller side. This is what most of my xhr controller actions look like. There are usually two possible outcomes to any action as well as processing other than simple view generation:
def whatever
render :update do |page|
if condition
some processing
page.replace_html... or some other rjs action
else
show_errors
end
end
end
@Yuval, I don't have much experience with large JavaScript code bases so I hesitate to say much here, but the convoluted code might be resolved through better organizing/structuring of the files and functions.
I don't think this is a problem specific to UJS. Any large code base has a high potential to turn into spaghetti code and JavaScript is no exception.
On the other hand, the event driven programming style is somewhat unique with UJS so that may play a part here. I hope others with more experience than I will chime in here.
Regarding your second question. The :update option is RJS and does still exist in Rails 3. See my earlier comment for my opinions on this.
I'll have to watch this later. Ryan if you are able to do an episode on converting a simple 2.3.5 app to work in 3.0.0beta, that would be awesome. I've been having trouble trying to do that myself.
@Romain, its possible it could bite you, returning false is basically just like calling e.preventDefault() and e.stopPropogation() meaning it will stop the browsers from handling it (example clicking a link will no longer follow it), and it also will prevent the event from bubbling up the DOM.
@Jamie, what your referring to is graceful degradation and not UJS, due to limited time constraints only the later was tackled, its possible it could be addressed in the future.
@Yuval, not sure how UJS further complicated your project, however you mention programmatic generation of JS, which is precisely what the UJS project has changed.
The helpers only generate the data-* attributes and nothing more, the jQuery and Prototype drivers are meant as an easy way of performing common functionality.
It's completely possible, to not include the rails.js file at all and write your own custom behaviors . Also if you dont like the js.erb approach each of the drivers have implemented custom callbacks ( ajax:before, ajax:complete, etc..) that you can hook into along the way $("#myform").live('ajax:complete', function() { ... }); where you could handle the response data in anyway you want (also allowing all your JS to be merged in one file and prevent continuously returning / evaling it from the server.
UJS allows more flexibility if you fall in the 20% of the 80/20 rule there are many ways to accomplish the same goals and the defaults may not always be be best for you but the important thing is that it is now very easy to step away from the golden path when it comes to JS.
Thanks Ryan and Steve for your feedback. Ultimately, I will most likely use the legacy plugin for any production projects that I update from Rails 2.x to 3. There are just too many variables. Down the road, as I work on new projects, I'll definitely have a look at a full UJS implementation. Cheers.
I really need to complete my thoughts before I post these comments. :)
In the case of an action with more than one outcome (i.e. all of them, if you're doing error handling) would I essentially just move my entire block of RJS logic (posted above) to a correspondingly named js.erb file? Would it still have access to private methods within the controller?
@Aaron, I plan to do an episode on upgrading a Rails 2 app to Rails 3 later. It will also act as a nice summary of the past Rails 3 episodes.
@Steve, thanks for the detailed responses here and your work on UJS in Rails.
@Yuval, The "js.erb" file acts as a view file, so it would not have access to controller methods. However you can move the methods into a Helper and it will be available in the view.
What is your opinion on the idea that executing remote received javascript is a bad idea as well and that we should stick to passing xml/json and replace the content in a callback instead?
@John, I like the convenience of returning JavaScript directly. Running it through JSON adds another layer of complexity that I don't find necessary.
That said, I have little experience with heavy JavaScript applications, so in those cases it may be cleaner to only use JSON responses and keep the logic/behavior all in one place.
The argument reminds me of YAML vs Ruby code for config files. I generally prefer Ruby code for configuration because of the additional power it brings. It works really well as long as that power isn't abused.
@Michael, I can see your point, especially on "data-remote" because it has no other purpose than to change behavior. In pure UJS the search form would have a "search" id with custom JavaScript to turn it into an AJAX request.
However that does require some custom, application-specific JavaScript which adds an extra step to making a form AJAX in Rails.
I think the aim is finding the benefits of UJS while keeping things as convenient as they were before. Here it is easy to swap out the JavaScript Rails driver which I think is one of the main purposes behind UJS in Rails.
@Michael there should be no need to update your views manually, when using the helpers provided to you by rails such as :confirm => "Are you sure?" will add these custom attributes for you.
I understand your point with css classes but with the number of Rails applications out there the chances of clashing with css classes people are already using are high so data- attributes were preferred especially being that this is the standard way of doing things like this in HTML 5.
The other debate with using css classes is for things like confirm, changing button text on submit etc, you can't supply data in the css class for those.
Using the data- attributes allows for a lot of versatility with changing the values inside of them etc without needing to swap css classes which will cause repaints and reflows.
Hope this gives a little more insight into the decision.
You are correct. The reason behind most of these decisions were to allow you to easily implement a driver for whatever framework you choose and the data you look for is consistent.
As well as the ability to easily override behavior.
For example:
jQuery users could easily override the confirm event and use a jQueryUI dialog to do the confirmation rather than using the standard javascript confirm box, or you can override some of the ajax events to open/close things like please wait layers, all of this can be done in a matter of minutes by overriding events.
It truly opens up a lot of areas for customization of standard rails behavior with very little effort.
once more a great screencast with exactly the info i need at the moment.
is there also a replacement for the in_place_editing plugin I used with rails 2?
How can i have the in_place_edit function again in rails3 (jquery) ?
many thanks.
@marcel, I believe many of the official Rails plugins will eventually be upgrade to Rails 3. I assume in_place_edit will, but I recommend asking on the rails-core mailing list. You can probably fork the plugin and contribute to the upgrade as well.
Ryan, thanx for all about rails 3
You renewed my excitement for rails espacially with this one.
I cant wait to start experimenting again.
And indeed the delete link has always been a dumb error in rails, too bad it still is. I already used your previous episode as inspiration for a plugin of mine, you can expect an update for rails 3 soon. Github resource_delete
There isn't really a need on the Rails side for observe_field and observe_form anymore so it was deprecated. It is just as much code to setup in your rails helper as to implement yourself in js
You would just use an event listener in your js framework of choice to watch for changes on the form field and perform the ajax call, or whatever action needs to be taken.
As an additional note the way observe_field and observe_form worked prior to rails 3 was inconsistent based on what options you gave it, whether or not it serialized the form, and what value was passed as the query param to your action. Which made the whole idea more complicated then it needed to be. Best to leave it to the developer to slap together some quick js to do the same thing in the same amount of code and intent to be 100% clear.
there is a legacy helper for anyone wanting to still use these pieces in their original form, with inline js.
There are no plans to support sortable_elements outside the legacy helper at this time as different frameworks tackle this differently, the amount of markup that would need to be emitted would take away from the cleanliness of the code.
Sortable Elements are easily tackled with javascript inside your javascript files, or by rendering out the javascript in a js.erb file.
Hi Ryan, and thank you so much for your great screencasts!
How does it come that when trying to render a js.erb template, rails3 (beta3) renders it with a text/html content-type (instead of text/javascript)? Am I missing something?
Thanks
Question concerning delete:
How may I perform an "ajax" delete in a list of products.
if attribute: data-method is specified rails.js handleMethod is called, which adds csrf params into a hidden form and form.submit is called. form.submit is nt performed as an ajax request.
Using data-remote instead of data-method would nt add csrf params.
Oh man, Ryan do something against the spam, it degrades the comments feature almost to be nonworthy ;)
Then: Thanks for all your GREAT work, it helps me a lot.
For this episode I have some criticism though: I think using button_to is just fine and no where ugly.
If you really want a confirmation then your link_to with confirmation page is great, but if you do not require a confirmation for graceful backfalls then button_to just fits perfectly.
The paradigm of using buttons where data might be modified and using links where data is merely returned to the user is rather transparent.
Furthermore you said that you can't do much about buttons looking as buttons? Thats not true at all.
a form,
a form input,
a form button {
display: inline;
margin: 0;
padding: 0;
/* more */
}
a form button,
a form input {
color: blue
}
a form button:hover,
a form input:hover {
text-decoration: underline;
}
@Volker: I was hoping to see an answer to the same question. You may have to handle this situation manually. I haven't looked in rails.js, but my guess is that we're still generating a form and submitting it, the difference being that it is being generated unobtrusively. However, as you noted, the form is not being submitted via AJAX.
If you take a look at episode 136, you'll see a way to submit forms via AJAX. You may have to attach a click event to your delete links which generates a form and submits it with AJAX. One problem I ran into with this approach is that the javascript in the js.erb response does not get evaluated. I couldn't figure out how to make this work, so instead I have my controller returning a JSON response and my deleteWithAjax function takes a handler as an argument. The handler will take care of removing the representation of the record from the DOM.
You might find it painstaking to create this form with the necessary authorization token in javascript. I have been experimenting with creating a javascript form builder. One of your included js files can make a get request to a controller and pass in a resource name and an id. The controller will find an object from those parameters and send down a js.erb file. That js.erb file has a FormBuilder constructor which returns an object that can spit out rails form builder tags for the object. When I call builder.form, I get the html generated by <%= form_for @object do |f| %> <% end %>, and during the call, it also dynamically adds properties to the builder object which will return text_field, text_area, select, and checkbox tags for the attributes of the object (which field it returns depends on the type of the attribute).
This is still in the works. Once it's ready I will post a blog about it and perhaps attach a link to this thread. So far it just spits out a form and some text_fields, but it's working great! For your delete form, you would have to change the method to "delete" in one of the hidden inputs, but other than that, you have a pre-packaged form which is ready to submitOrDeleteWithAjax and use!
Can you explain the render @products part? I think something is missing in your controller. I looked thru the source code, and I don't see how it could work as is.
I am having a problem getting this to work. The request header isn't being set to javascript so the controller isn't rendering the .js template (in FF it is shown as being set to "*/*" and Safari it shows application/xml). See the link for more info.
Can we use unobtrusive javascript to implement features like autocomplete in jquery? or should I use the public/javscripts folder and reference each javascript that interests one of my views separately?
in the index.js.erb file, it always expects a partial to be available in app/views/products/_product.html.erb. Why is that so and is there any way to skip this?
I just wanted to share a neat way to debug remote JavaScript errors and notify Airbrake that we used in a recent project. Debugging RJS and Airbrake Integration
This doesn't work for rails 3.2.5.
I've removed 3.0.0beta from Gemfile and issued bundle install but when I try to run server with:
rails server
I'm getting error: https://gist.github.com/3098891
This is not an issue specifically with this episode's code. You upgraded from 3.0 to 3.2. Rails already told you what you need to do. Two things:
You did not specify how you would like Rails to report deprecation notices for your development environment, please set config.active_support.deprecation to :log at config/environments/development.rb
You need to remove the debug_rjs config option from your environment files as it was deprecated in 3.1 and removed in 3.2.
I did like you said but it raised another error so I decided to search for another tutorial. I've found http://notes.rehali.com/?p=97 very useful for me. Thanks for help.
I'm interested in understanding the best practice for view/partial specific javascript.
I could use a yield statement at the top of my view/partial to fill in a javascript_include_tag in application.html.erb, but this leads to multiple HTTP requests to serve assets in production. Also, you need to do some hacks for it to work well with asset pre-compilation.
I'd appreciate it if someone could point me in the right direction. Even more so if someone could convince Ryan to do an updated screencast on this one!
Hi,
Could use a second opinion on this - I have an IF statement block in my UJS file - and the if condition is not satisfied (confirmed by putting a js alert in there) . However - the block seems to get executed - the console is showing the database queries in that block being executed. Cant seem to make sense of it - thoughts ?
Nice screencast, thanks. I wonder if the rjs stuff is still in rails 3? I'm using it a lot, it simplifies working with javascript quite a bit. For example by making helpers that output js via the update_page function. Is that still supported in rails 3?
Hello Ryan, like usually, thanks for your work. :)
In the javascript code, why do you use "return false;" instead of "event.preventDefault();" ?
And i have a suggestion for a unobstrusive links with actions methods : the idea is to use the noscript tag to provide a button_to if scripts are disabled and link_to in normal cases.
Of course, the other way is to use only buttons for actions, with nice styles. :)
Sephi-Chan
Thanks, this screencast is much appreciated. I am also wondering about RJS and Rails 3? I have used RJS with much joy in that past and I am hoping that it would still be supported in Rails 3.
I've made a simple init generator which will download the latest rails.js (jquery) and doing some other stuff: http://github.com/mendelbenjamin/rhj_init
Thanks again Ryan
How do you do it? You always seem to come up with Railscasts that hit exactly what I'm looking for... anyways, thanks for another great tutorial!
Thanks for another great screencast...
I still use Rails 2.3 in Windows OS, and actually not much satisfied...
Does it still functional in older Rails version?
What happens if the user is not using a HTML 5 capable browser? I imagine it will be quite a few years until you can assume that all your users have HTML 5.
Great screencast though!
Martin
@Nico, @Willem - rails 3 still contains RJS via http://github.com/rails/prototype_legacy_helper and only available for prototype, however nothing prevents you from creating a js.erb view containing the javascript you would like executed
@Romain - event.preventDefault only prevents the browsers default action, returning false stops the event from propogating (including other handlers)
@Martin - the data-* attributes function in all major browsers, however it will not validate as custom attributes are not part of the HTML spec until HTML5
@Steve: So to have a rails helper that outputs js I could e.g. render a js.erb partial in a helper? Is that what you mean? Anyway rjs had some nice functionality. Abstracting away from the actual js using ruby is nice. I liked that...
@Steve : Ok i see. So in a "real" application it's quite dangerous to use "return false;", no ?
I still maintain that there should be a "delete" GET action by default similar to how we have "edit" for update. This would allow everything to work without javascript, is this not the whole point in unobtrusive javascript.
I wrote an article back in 2006 outlining why this is a good idea http://thelucid.com/2006/07/26/simply-restful-the-missing-action/
@Nico, Yes, you can render a js.erb partial if you need to generate JavaScript in a helper.
I rarely find the need to use RJS anymore. It worked well back when I could not stand JavaScript, but jQuery and other frameworks make JavaScript much nicer to work with.
Simple things like JavaScript "if" conditions are very ugly to do with RJS. I encourage you to learn to use JavaScript directly and it will be more flexible.
@Romain, in what way is "return false" dangerous? It basically tells the browser to not follow the "href" part of the link.
@Jamie, I can understand both sides here. In some ways I would like to see a "delete" action be there by default, but the implementation of the confirmation page would be a lot of duplication across controllers.
Certainly Rails could handle the confirmation page behind the scenes but I think that kind of implementation fits better in a plugin. I hope with Rails 3's approach to plugins it will be much nicer to write a plugin which extends "resources" in routes and adds a delete action and view.
I'll post this on your blog post as well which is probably the best place to continue the discussion.
Thanks for the cast Ryan. I know this comment won't be popular, but I have very mixed feelings about UJS.
I've worked on big ajax-heavy production projects with both prototype helpers and UJS JQuery, and the UJS projects inevitably ended up more obtrusive and convoluted. Mostly because of the sheer quantity of javascript files needed, as well as programatically generating javascript in rails or C# (gross) once you get into more complex tasks.
I'll still give this a try but remain somewhat skeptical.
Was also wondering if render :update still exists unaltered on the controller side. This is what most of my xhr controller actions look like. There are usually two possible outcomes to any action as well as processing other than simple view generation:
def whatever
render :update do |page|
if condition
some processing
page.replace_html... or some other rjs action
else
show_errors
end
end
end
This is vital functionality. Cheers.
@Yuval, I don't have much experience with large JavaScript code bases so I hesitate to say much here, but the convoluted code might be resolved through better organizing/structuring of the files and functions.
I don't think this is a problem specific to UJS. Any large code base has a high potential to turn into spaghetti code and JavaScript is no exception.
On the other hand, the event driven programming style is somewhat unique with UJS so that may play a part here. I hope others with more experience than I will chime in here.
Regarding your second question. The :update option is RJS and does still exist in Rails 3. See my earlier comment for my opinions on this.
I'll have to watch this later. Ryan if you are able to do an episode on converting a simple 2.3.5 app to work in 3.0.0beta, that would be awesome. I've been having trouble trying to do that myself.
Thanks.
@Romain, its possible it could bite you, returning false is basically just like calling e.preventDefault() and e.stopPropogation() meaning it will stop the browsers from handling it (example clicking a link will no longer follow it), and it also will prevent the event from bubbling up the DOM.
@Jamie, what your referring to is graceful degradation and not UJS, due to limited time constraints only the later was tackled, its possible it could be addressed in the future.
@Yuval, not sure how UJS further complicated your project, however you mention programmatic generation of JS, which is precisely what the UJS project has changed.
The helpers only generate the data-* attributes and nothing more, the jQuery and Prototype drivers are meant as an easy way of performing common functionality.
It's completely possible, to not include the rails.js file at all and write your own custom behaviors . Also if you dont like the js.erb approach each of the drivers have implemented custom callbacks ( ajax:before, ajax:complete, etc..) that you can hook into along the way $("#myform").live('ajax:complete', function() { ... }); where you could handle the response data in anyway you want (also allowing all your JS to be merged in one file and prevent continuously returning / evaling it from the server.
UJS allows more flexibility if you fall in the 20% of the 80/20 rule there are many ways to accomplish the same goals and the defaults may not always be be best for you but the important thing is that it is now very easy to step away from the golden path when it comes to JS.
Aaron, this might help. http://blog.peepcode.com/tutorials/2010/live-coding-rails-3-upgrade
Thanks Ryan and Steve for your feedback. Ultimately, I will most likely use the legacy plugin for any production projects that I update from Rails 2.x to 3. There are just too many variables. Down the road, as I work on new projects, I'll definitely have a look at a full UJS implementation. Cheers.
I really need to complete my thoughts before I post these comments. :)
In the case of an action with more than one outcome (i.e. all of them, if you're doing error handling) would I essentially just move my entire block of RJS logic (posted above) to a correspondingly named js.erb file? Would it still have access to private methods within the controller?
@Aaron, I plan to do an episode on upgrading a Rails 2 app to Rails 3 later. It will also act as a nice summary of the past Rails 3 episodes.
@Steve, thanks for the detailed responses here and your work on UJS in Rails.
@Yuval, The "js.erb" file acts as a view file, so it would not have access to controller methods. However you can move the methods into a Helper and it will be available in the view.
What is your opinion on the idea that executing remote received javascript is a bad idea as well and that we should stick to passing xml/json and replace the content in a callback instead?
@John, I like the convenience of returning JavaScript directly. Running it through JSON adds another layer of complexity that I don't find necessary.
That said, I have little experience with heavy JavaScript applications, so in those cases it may be cleaner to only use JSON responses and keep the logic/behavior all in one place.
The argument reminds me of YAML vs Ruby code for config files. I generally prefer Ruby code for configuration because of the additional power it brings. It works really well as long as that power isn't abused.
Ryan, thanks a lot for this great introduction into the use of Javascript in Rails 3.
It does seem to me, however, adding custom tags in order to get javascript functionality running, is not _really_ unobstrusive.
At least not, the way I understand unobstrusive.
It is, after all, _extra_ code added for the single and sole purpose of getting your javascript running.
Maybe this sounds too purist. I am aware of the fact, that at some point, you need to set some "hooks" from where the javascript events take off.
To me, it would have seemed a simpler approach, if one could simply use e.g. css classes, which are already available in the code, as markers.
I don't think, I want to go through all my views and add custom markers.
Just my five cents.
Michael Kastner
@Michael, I can see your point, especially on "data-remote" because it has no other purpose than to change behavior. In pure UJS the search form would have a "search" id with custom JavaScript to turn it into an AJAX request.
However that does require some custom, application-specific JavaScript which adds an extra step to making a form AJAX in Rails.
I think the aim is finding the benefits of UJS while keeping things as convenient as they were before. Here it is easy to swap out the JavaScript Rails driver which I think is one of the main purposes behind UJS in Rails.
@Michael there should be no need to update your views manually, when using the helpers provided to you by rails such as :confirm => "Are you sure?" will add these custom attributes for you.
I understand your point with css classes but with the number of Rails applications out there the chances of clashing with css classes people are already using are high so data- attributes were preferred especially being that this is the standard way of doing things like this in HTML 5.
The other debate with using css classes is for things like confirm, changing button text on submit etc, you can't supply data in the css class for those.
Using the data- attributes allows for a lot of versatility with changing the values inside of them etc without needing to swap css classes which will cause repaints and reflows.
Hope this gives a little more insight into the decision.
@Ryan
You are correct. The reason behind most of these decisions were to allow you to easily implement a driver for whatever framework you choose and the data you look for is consistent.
As well as the ability to easily override behavior.
For example:
jQuery users could easily override the confirm event and use a jQueryUI dialog to do the confirmation rather than using the standard javascript confirm box, or you can override some of the ajax events to open/close things like please wait layers, all of this can be done in a matter of minutes by overriding events.
It truly opens up a lot of areas for customization of standard rails behavior with very little effort.
once more a great screencast with exactly the info i need at the moment.
is there also a replacement for the in_place_editing plugin I used with rails 2?
How can i have the in_place_edit function again in rails3 (jquery) ?
many thanks.
@marcel, I believe many of the official Rails plugins will eventually be upgrade to Rails 3. I assume in_place_edit will, but I recommend asking on the rails-core mailing list. You can probably fork the plugin and contribute to the upgrade as well.
Ryan, thanx for all about rails 3
You renewed my excitement for rails espacially with this one.
I cant wait to start experimenting again.
And indeed the delete link has always been a dumb error in rails, too bad it still is. I already used your previous episode as inspiration for a plugin of mine, you can expect an update for rails 3 soon. Github resource_delete
Nice example, as alwais, but what about "observe_field" in UJS?
@assente
There isn't really a need on the Rails side for observe_field and observe_form anymore so it was deprecated. It is just as much code to setup in your rails helper as to implement yourself in js
You would just use an event listener in your js framework of choice to watch for changes on the form field and perform the ajax call, or whatever action needs to be taken.
As an additional note the way observe_field and observe_form worked prior to rails 3 was inconsistent based on what options you gave it, whether or not it serialized the form, and what value was passed as the query param to your action. Which made the whole idea more complicated then it needed to be. Best to leave it to the developer to slap together some quick js to do the same thing in the same amount of code and intent to be 100% clear.
there is a legacy helper for anyone wanting to still use these pieces in their original form, with inline js.
What about sortable_elements, for example? In Rails 3 beta it still uses inline javascript. Does anyone knows if this is also likely to change?
@Cassio
There are no plans to support sortable_elements outside the legacy helper at this time as different frameworks tackle this differently, the amount of markup that would need to be emitted would take away from the cleanliness of the code.
Sortable Elements are easily tackled with javascript inside your javascript files, or by rendering out the javascript in a js.erb file.
I might be worng but you do not need to escape html in the view now because of safe_buffer in rails3. Isn't that correct?
Hi Ryan, and thank you so much for your great screencasts!
How does it come that when trying to render a js.erb template, rails3 (beta3) renders it with a text/html content-type (instead of text/javascript)? Am I missing something?
Thanks
Question concerning delete:
How may I perform an "ajax" delete in a list of products.
if attribute: data-method is specified rails.js handleMethod is called, which adds csrf params into a hidden form and form.submit is called. form.submit is nt performed as an ajax request.
Using data-remote instead of data-method would nt add csrf params.
What s the best approach to achieve that?
Hi,
Why is it that I can submit a form only once?
I think it's because the security_tags aren't update, but I don't know how to get around that.
Any advice?
Thank you
Oh man, Ryan do something against the spam, it degrades the comments feature almost to be nonworthy ;)
Then: Thanks for all your GREAT work, it helps me a lot.
For this episode I have some criticism though: I think using button_to is just fine and no where ugly.
If you really want a confirmation then your link_to with confirmation page is great, but if you do not require a confirmation for graceful backfalls then button_to just fits perfectly.
The paradigm of using buttons where data might be modified and using links where data is merely returned to the user is rather transparent.
Furthermore you said that you can't do much about buttons looking as buttons? Thats not true at all.
a form,
a form input,
a form button {
display: inline;
margin: 0;
padding: 0;
/* more */
}
a form button,
a form input {
color: blue
}
a form button:hover,
a form input:hover {
text-decoration: underline;
}
@Volker: I was hoping to see an answer to the same question. You may have to handle this situation manually. I haven't looked in rails.js, but my guess is that we're still generating a form and submitting it, the difference being that it is being generated unobtrusively. However, as you noted, the form is not being submitted via AJAX.
If you take a look at episode 136, you'll see a way to submit forms via AJAX. You may have to attach a click event to your delete links which generates a form and submits it with AJAX. One problem I ran into with this approach is that the javascript in the js.erb response does not get evaluated. I couldn't figure out how to make this work, so instead I have my controller returning a JSON response and my deleteWithAjax function takes a handler as an argument. The handler will take care of removing the representation of the record from the DOM.
You might find it painstaking to create this form with the necessary authorization token in javascript. I have been experimenting with creating a javascript form builder. One of your included js files can make a get request to a controller and pass in a resource name and an id. The controller will find an object from those parameters and send down a js.erb file. That js.erb file has a FormBuilder constructor which returns an object that can spit out rails form builder tags for the object. When I call builder.form, I get the html generated by <%= form_for @object do |f| %> <% end %>, and during the call, it also dynamically adds properties to the builder object which will return text_field, text_area, select, and checkbox tags for the attributes of the object (which field it returns depends on the type of the attribute).
This is still in the works. Once it's ready I will post a blog about it and perhaps attach a link to this thread. So far it just spits out a form and some text_fields, but it's working great! For your delete form, you would have to change the method to "delete" in one of the hidden inputs, but other than that, you have a pre-packaged form which is ready to submitOrDeleteWithAjax and use!
Can you explain the render @products part? I think something is missing in your controller. I looked thru the source code, and I don't see how it could work as is.
I am having a problem getting this to work. The request header isn't being set to javascript so the controller isn't rendering the .js template (in FF it is shown as being set to "*/*" and Safari it shows application/xml). See the link for more info.
Thanks
Can we use unobtrusive javascript to implement features like autocomplete in jquery? or should I use the public/javscripts folder and reference each javascript that interests one of my views separately?
Please advise
Hi Ryan,
That is very helpful. Wasn't aware that integration of HTML 5 with Rails 3 will be so simple and doesn't require unnecessary lines of code.
One small doubt: When we write this code:
in the index.js.erb file, it always expects a partial to be available in app/views/products/_product.html.erb. Why is that so and is there any way to skip this?
Best Regards
Puneet
I just wanted to share a neat way to debug remote JavaScript errors and notify Airbrake that we used in a recent project. Debugging RJS and Airbrake Integration
This doesn't work for rails 3.2.5.
I've removed 3.0.0beta from Gemfile and issued bundle install but when I try to run server with:
rails server
I'm getting error:
https://gist.github.com/3098891
This is not an issue specifically with this episode's code. You upgraded from 3.0 to 3.2. Rails already told you what you need to do. Two things:
You did not specify how you would like Rails to report deprecation notices for your development environment, please set config.active_support.deprecation to :log at config/environments/development.rb
You need to remove the
debug_rjs
config option from your environment files as it was deprecated in 3.1 and removed in 3.2.Hope this helps.
I did like you said but it raised another error so I decided to search for another tutorial. I've found http://notes.rehali.com/?p=97 very useful for me. Thanks for help.
Nominating this article for an update.
I second that. We got the backbone.js but I'd like to see something that isn't quite so heavy.
+1 for an update ;)
Nominating this article for an update too.
I'm interested in understanding the best practice for view/partial specific javascript.
I could use a yield statement at the top of my view/partial to fill in a javascript_include_tag in application.html.erb, but this leads to multiple HTTP requests to serve assets in production. Also, you need to do some hacks for it to work well with asset pre-compilation.
I'd appreciate it if someone could point me in the right direction. Even more so if someone could convince Ryan to do an updated screencast on this one!
Hi,
Could use a second opinion on this - I have an IF statement block in my UJS file - and the if condition is not satisfied (confirmed by putting a js alert in there) . However - the block seems to get executed - the console is showing the database queries in that block being executed. Cant seem to make sense of it - thoughts ?
What happens if I use method: :get in link_to? Does that make any effect on loading of the page?