How to Use Coffeescript in the Views Executed on Render.Js

Can I use CoffeeScript in the views executed on render.js?

It's not yet supported in 3.1. You will need to use Coffeebeans.


Update: It is now supported in rails 3.2

Include a Coffeescript file with ERB in a view

You can kinda use erb in the asset pipeline, but you have to remember that it only gets rendered ONCE, EVER, and not once for every user and so even if there was an @user variable (which there won't be), it would never change. You can use erb in your coffee file for things like route paths and environment variables, but not for things like user-specific config and dynamic changes to the JS. It's bad practice anyway.

What you should really do is use a javascript library to read cookies instead of trying to do it with rails (This will give you access to some of the things you appear to be trying to do). And when you need more dynamic behavior you should render data-attributes or other values into the html DOM itself and use the javascript to read that.

Take a look at this cookie library: https://github.com/carhartl/jquery-cookie

There's many others to look at via a quick google search.

socket.onopen = =>
console.log("Connection Open")
init = {
sender: "cp"
action: "init"
user: $.cookie('user_id')
token: $.cookie('remember_token')
}

There are a couple of ways to render new markup for your view using JS. One way is to use js templates. I'm a big fan of the hamlcoffeeassets library here: https://github.com/netzpirat/haml_coffee_assets Although it uses haml for the view, and not ERB. There are ERB variants as well.

You would add some markup to app/assets/templates/friend.jst.hamlc like so:

%p This is my friend markup #{@friend.name}

And then you can render it from your JS like this:

$('#friends').append(JST['templates/friend'](friend: {name: 'Bob'}))

Which will append the markup from your template with the values you've passed interpolated in. In my example you'd end up with this markup inside your #friends container:

<p>This is my friend markup Bob</p>

Alternatively you can render the partial you want via rails into your JSON response as just a string, and then insert that into your document...

So your JS might look something like this:

socket.onmessage = (m)=>
console.log("Recieved: #{m.data}")
msg = m.data.JSON.parse
switch msg.action
when "ret_init"

when "friend_udt"
refreshFriend(msg.friendHTML)

refreshFriend(html) ->
$('#friends').html(html)

UPDATE

In reference to your ERB question... First of all your partial is incredibly inefficient making similar calls to the database four times every time you render it. haml_coffee_assets is for use with the haml markup language (which I prefer over ERB), if you want ERB then use eco instead: https://github.com/sstephenson/eco

If you want to render this in the JS, then you need to send this "friend relation" data as JSON through the notification data response, you do not have access to active record OR any controller methods or instance variables when rendering javascript partials - they don't hit back to the server, they only use what is accessible by your javascript at the time.

j render With Coffeescript in Rails and Understanding How to Sanitize Javascript

To answer your first portion about escaping Javascript let's take a look at this code:

$blogPost = "<%= j render(@blog.content) %>"

Now imagine a user decided to begin their blog post with a quote from DHH:

“Workaholics don't actually accomplish more than nonworkaholics.” 

Now since Javascript in this context happens on the client-side, the Ruby in your code gets evaluated first. Thus your Javascript now looks like this:

$blogPost = "“Workaholics don't actually accomplish more than nonworkaholics.”"

As you can see, there is an extra set of quotes in there which breaks out of the string. The actual quote is going to be read as Javascript by the interpreter, which will break because that is invalid Javascript. A malicious user could take advantage of this by rewriting their blog post to contain Javascript instead of a quote. To fix this we escape the quotes with j (short for escape_javascript), so:

“Workaholics don't actually accomplish more than nonworkaholics.”

Becomes:

\"Workaholics don't actually accomplish more than nonworkaholics.\"

Now onto your second portion. The reason your code is literally returning "j render(@blog.content)" is because that part of your code is Ruby and needs to be handled by ERB before your Javascript gets sent to the browser. To have ERB handle this file, simply add .erb to your file name:

assets/javascripts/blogs.coffee.erb

However, this is a bad practice because the Javascript in your assets is in a different context than your app so I suspect it will not find the @blogs variable. Thus you should move your blogs.coffee.erb file to the appropriate view folder, something like this:

app/views/blogs/index.coffee.erb

(Though once you move it into the views, I believe the .erb is no longer needed, as Rails implies it)

Cannot render coffeescript partial inside coffeescript

That's because _update_some_stuff.js.coffee is interpreted and converted to Javascript. When it is inserted into on_page_load.js.coffee it raises an error because vanilla Javascript code is not compatible inside a Coffee-Script file (the function keyword in this case).

How do you render HTML tags in React with Coffeescript?

Here's what finally worked

React = require('react')
PropTypes = require('prop-types')
ReactDom = require('react-dom-factories')
createReactClass = require('create-react-class')
{div, h1} = ReactDom

Rows = createReactClass
render: ->
div
className: 'col-md-12'
h1
className: 'title'
'Rows'

export default Rows

So I've been using React 16 and it's incredible how many things have changed in the last 6 months. I'm TOTALLY new to React, so I had absolutely no idea how this worked, but I managed to use the code above without errors.

First:

ReactDom = require('react-dom-factories')

This is the one I was missing. I was getting errors that div and h1 weren't functions, or weren't defined. So it turns out that per the documentation React.DOM is now available as react-dom-factories:

The deprecations introduced in 15.x have been removed from the core
package. React.createClass is now available as create-react-class,
React.PropTypes as prop-types, React.DOM as react-dom-factories,
react-addons-test-utils as react-dom/test-utils, and shallow renderer
as react-test-renderer/shallow.

Second:

If anyone else runs onto this and you get errors that say Cannot find module "react-dom-factories", it means you have to add them to your webpacker with this:

yarn add react-dom-factories

You may also have to add create-react-class and prop-types, if you're following my example above.

Lastly:

Be sure the extension of your coffeescript file is simply .coffee. If you use .js.coffee or .jsx.coffee you'll get errors that the component cannot be found.

I'm not 100% sure if this is necessary, but I also added cjsx-loader to my webpacker when I was searching for a solution. It's a coffee-react-transform loader module for Webpack.

UPDATE: This last part wasn't necessary. I made a new project and this wasn't required at all.



Related Topics



Leave a reply



Submit