netzpirat / haml-coffee

Haml templates where you can write inline CoffeeScript.
http://haml-coffee-online.herokuapp.com/
MIT License
442 stars 51 forks source link

Globally accessible helpers - best approach to do this. #25

Closed michaltaberski closed 12 years ago

michaltaberski commented 12 years ago

Hi,

I would like to ask you what is the best approach to create a globally accessible helper lib?

I mean I would like to create a few (ralis like) methods (look below), wich I could use in every template. I am using haml-coffee with haml_coffee_assets.

- sum = (a, b) ->
  %div
    %span= a
    %span= b
    %span= a+b
netzpirat commented 12 years ago

haml_coffee_assets has a global context that is mixed into each local (template) context, so you can share global data or helper functions defined at a central place. You can read more about under the "Global context" section in the haml_coffee_assets readme.

However, you won't have access to the haml-coffee parser and you have to rewrite your example to plain JavaScript, like

HAML.globals = ->
  {
    sum: (a,b) -> $("<div><span>#{ a }</span><span>#{ b }</span><span>#{ a + b }</span></div>")
  }

A good option is to use something like Jaml in your helper function.

michaltaberski commented 12 years ago

thx for answer, now when I know about HAML.globals its much easier. I think there is a kind of solution to achieve helpers with haml-coffee sytnax too.

I didn't test it yet, but what about solution like:

put all "helpers" to separate templates files under the helper/ folder and later do something like:


HAML.globals = ->
  helpers = {}
  for key, templateFunction of JST
   helperName = key.match(/helper\/(.+)/)[1]
   if helperName
     helpers[helperName] = templateFunction
  _.extend( helpers, {
      # other methods here
  })

Do you predict any disadvantages ?

madsheep commented 12 years ago

Using JST namespace 'helpers' to write view helpers also gives you very simple and clean way to add/write new helpers to the views. We are thinking about putting all helpers we written in to some gem, so everybody c'd use link_to in jst views. I have this strange filling @chytreg might have some ideas on the subject?

chytreg commented 12 years ago

@madsheep I use only HAML.global nothing sophisticated. Here is the gist with my HTML helpers: https://gist.github.com/802d87e1fd6495cc4727

I like to pass an backbone model to my form builder to have usage quite similar like simple_form has.

@michaltaberski How do you want implement the function link_to as an JST template and the bind to haml globals? I like the concept of helper structure but I don't see how it will work.

michaltaberski commented 12 years ago

@chytreg below I present primitive case of link_to

create helper/link_to.hamlc with


%a{href: "#{@link}"}= "#{@name}"

So in app js code you already have function

JST['helper/link_to']

so if you

globally run


HAML.globals = ->
  helpers = {}
  for key, templateFunction of JST
   helperName = key.match(/helper\/(.+)/)[1]
   if helperName
     helpers[helperName] = templateFunction
  _.extend( helpers, {
      # other methods here
  })

in other template you can use

%h1= "My super header"
= link_to name: 'Go to there...', link:'/' 

Just there is one more thing we need to be aware of. You need to switch of the escaping HTML or you need to use helpers with != like so:

%h1= "My super header"
!= link_to name: 'Go to there...', link:'/' 
chytreg commented 12 years ago

Nice, but can we easily achieve syntax similar to Rails one?

I prefer

  = link_to 'Go to there', '/'

rather than

  = link_to name: 'Go to there...', link:'/' 
michaltaberski commented 12 years ago

not by default, but you can always do sth like:


HAML.globals = ->
  helpers = {}
  helpers['link_to'] = (name, link)->  
    JST['helper/link_to'](name: name, link: link)
  _.extend( helpers, {
      # other methods here
  })
netzpirat commented 12 years ago

This is such a great discusion, that I moved the code snippets slightly refactored to the Haml Coffee Assets Wiki. Thanks to all who participated.

I'm closing this now, since it really belongs to Haml Coffee Assets. Feel free to open a pull request for a beginning of a helper collection :P

steel commented 11 years ago

Here's another example.

I wanted to be more lazy and preserve default argument values so I wrote a helper to convert the arguments list into an object to pass into JST.

#= require_tree ./templates/helpers

HAML.globals = ->
  {
    argumentsToObject: ->
      argDefs = arguments.callee.caller.toString().match(/\(.*?\)/)[0]
      argNames = argDefs.replace(/[()\s]/g,'').split(',')

      _.object argNames, arguments

    theme: (label, themeName, themeId, hiddenClass='') ->
      JST['templates/helpers/theme'](@argumentsToObject.apply this, [label, themeName, themeId, hiddenClass])

    check_box: (propertyName, propertyValue) ->
      JST['templates/helpers/check_box'](@argumentsToObject.apply this, [propertyName, propertyValue])

    color_picker: (label, propertyName, flashValue) ->
      JST['templates/helpers/color_picker'](@argumentsToObject.apply this, [label, propertyName, flashValue])

    sizer: (label, propertyName, min='0', max='1', step='0.05', value='0') ->
      JST['templates/helpers/sizer'](@argumentsToObject.apply this, [label, propertyName, min, max, step, value])
  }