Injecting variable values into javascript and HAML in RoR
Asked Answered
H

2

59

I have the following function for using ZenDesk. I'd like to inject my current_user details into the form as follows. (this is my from html.haml template). However I cannot figure out how to make this work.

:javascript
    if (typeof(Zenbox) !== "undefined") {
      Zenbox.init({
        dropboxID:   "xxxxx",
        url:         "xxxxx.zendesk.com",
        tabID:       "support",
        tabColor:    "black",
        tabPosition: "Left",
        requester_name:  =current_user ? "#{current_user.first_name} #{current_user.last_name}" : "" ,
        requester_email: =current_user ? "#{current_user.email}" : "" ,
        hide_tab: true
        });
    }

In short, how does one inject rails variables into a :javascript element in haml.

Hylo answered 16/1, 2011 at 22:1 Comment(1)
The answers will be the same without HAML: #2465466Coextensive
E
68

This should work ie. put all inline ruby inside of #{}:

requester_name:  "#{current_user.first_name + ' ' + current_user.last_name if current_user}",
requester_email: "#{current_user.email if current_user}",
Eosinophil answered 16/1, 2011 at 22:6 Comment(2)
And how about the reverse direction? i.e. :javascript #{raw some_helper(ARGUMENTS FROM JS HERE)}Flag
Javascript runs in a browser and ruby on server so you can't do it like that.Eosinophil
C
35

Direct #{} works for simple strings, but is not the most scalable / safe solution in general.

For example, the literal backslash in Ruby would cause you problems in Javascript where it will be interpreted as a newline character:

- a = "\\n"
:javascript
  '#{ a }' !== "\\n"

From this awesome Rails cast, the following techniques can be used:

escape_javascript

Alias: j.

Works only on strings.

Escapes characters that can have special meanings in Javascript strings, like backslash escapes, into a format suitable to put inside Javascript string literal quotes.

Maintain html_safe status of input, so needs html_safe otherwise special HTML chars like < would get escaped into &lt;.

- a = "\\n<"
:javascript
  '#{ j(a)           }' === '\\n&lt;'
  '#{ j(a).html_safe }' === '\\n<'

to_json + html_safe

Works because JSON is almost a subset of Javascript object literal notation.

Works on any hash object, including strings, arrays and integers which are converted to JSON fragments of the corresponding data type.

- data = { key1: 'val1', key2: 'val2' }
:javascript
  data = #{ data.to_json }
  data.key1 === 'val1'
  data.key2 === 'val2'

data- attributes

Add values to attributes, retrieve them with Javascript DOM operations.

Better with the content_tag helper:

= content_tag 'div', '', id: 'data', data: {key1: 'val1', key2: 'val2'}
:javascript
  $('#data').data('key1') === 'val1'
  $('#data').data('key2') === 'val2'

gon

Library specialized for the job: https://github.com/gazay/gon

Probably the most robust solution.

Gemfile:

gem 'gon'

Controller:

gon.key1 = 'val1'
gon.key2 = 'val2'

Layout app/views/layouts/application.html.erb:

<html>
<head>
  <meta charset="utf-8"/>
  <%= include_gon %>

View:

:javascript
  gon.key1 === 'val1'
  gon.key2 === 'val2'
Coextensive answered 27/6, 2014 at 16:23 Comment(1)
Downvoters please explain so I can improve info. I never retaliate. Thanks.Coextensive

© 2022 - 2024 — McMap. All rights reserved.