ai / evil-blocks

Tiny framework for web pages to split your app to separated blocks
MIT License
131 stars 10 forks source link

Does it work with turbolinks? #41

Closed Hirurg103 closed 6 years ago

Hirurg103 commented 6 years ago

I have the following evil block

$(document).on 'turbolinks:load', ->

  evil.block '@@subscription-form',
    init: ->
      console.log 'init'

subscription form is present on the subscriptions index and also loaded via ajax when user clicks on Add another subscription

when I go to the other page and navigate back, click on the Add another subscripton I see

init (2) init (2) init init

in the console

subscriptions/index.html.slim, subscriptions/_new.html.slim and subscriptions/new.js.erb look like this

# subscriptions/index.html.slim
#new-subscription
  = render 'subscriptions/new'
...
# subscriptions/_new.html.slim
@@subscription-form
  = simple_form_for @subscription, remote: true do |f|
    = render 'subscriptions/fields', f: f
javascript:
  evil.block.vitalize($('@@subscription-form'));
# subscriptions/new.js.erb
$('#new-subscription').append("<%= j render 'subscriptions/new' %>").show();

The problem is that subscription block initializes several times on the @@subscription-form. Could you help me with this please?

I use evil-blocks-rails (0.7.0)

ai commented 6 years ago

You should call evil.black only once. Much better to call evil.block.enlive() (check docs, I am working for phone and don't remember the method name exactly).

Hirurg103 commented 6 years ago

Hello @ai

You should call evil.black only once

Got it, thanks!

Much better to call evil.block.enlive()

I haven't found enlive in the sources. I suppose that you meant vitalize


BTW How do you think it will be better to organize the JS with turbolinks

  1. call vitalize on turbolinks:load and in the subscriptions/new.js.erb template like this
evil.block '@@subscription-form',
  init: ->
    console.log 'init'

$(document).on 'turbolinks:load', ->
  evil.block.vitalize('@@subscription-form')
# subscriptions/new.js.erb
$('#new-subscription').append("<%= j render 'subscriptions/new' %>").show();
evil.block.vitalize('@@subscription-form')
  1. call vitalize at the bottom of the subscription form template
    # subscriptions/_new.html.slim
    @@subscription-form
    = simple_form_for @subscription, remote: true do |f|
    = render 'subscriptions/fields', f: f
    javascript:
    evil.block.vitalize('@@subscription-form');
ai commented 6 years ago

I haven't found enlive in the sources. I suppose that you meant vitalize

Exactly

call vitalize at the bottom of the subscription form template

Having a inline JS (JS directly in the HTML inside <script>) is a bad practice. First, it will not allow you to make proper XSS protection (by CSP headers). Second, it will not be cached as separated JS files.

So first solution (with turbolinks:load event listener in separated JS file is a much better way).

Hirurg103 commented 6 years ago

Thank you for the recommendations, @ai !