Skip to content
This repository has been archived by the owner on Jul 28, 2018. It is now read-only.

Selector-based replace #616

Open
firedev opened this issue Oct 7, 2015 · 9 comments
Open

Selector-based replace #616

firedev opened this issue Oct 7, 2015 · 9 comments

Comments

@firedev
Copy link

firedev commented Oct 7, 2015

Hi,

After working a bit with Cells and Trailblazer I have adopted some concepts from React.js and built view-less system where updates are happening from the controller. It looks a bit like Turbolinks3:

class CalendarController
    def update
     ...
      update_cells(
        concept('worktime/form', @worktime),
        concept('calendar/day', day),
        concept('calendar/stat', day.month, user: current_user)
      )
    end
end

update_cells just calls update method on each concept and glues the resulting JavaScripts together:

class ApplicationController
  def update_cells(*cells)
    render text: cells.flatten.join
  end
end

Each cell has it's unique-ish document identifier, but instead of id I use unique CSS class.

Why?

That allows me to do sweeping updates on the page. When one cell is changed, it is being re-rendered everywhere in the document. And the only thing that stops me from jumping on Turbolinks3 train is that Turbolinks uses id.

Is there a way to replace document fragments based on CSS class? Was it even considered? Why not?

Thanks.

@tortuetorche
Copy link

Hi @firedev,

In the Turbolinks docs, there is a concept of namespaced ids, maybe you can use it instead of CSS class?

If the id contains a colon, the key before the colon can also be targeted to replace many nodes with a similar prefix.

<div id="comments:1"></div>
<div id="comments:2"></div>
<!-- ... -->
<div id="comments:12"></div>

Cheers,
Tortue Torche

@firedev
Copy link
Author

firedev commented Oct 7, 2015

Yep, that is the problem. I don't have the luxury of React that keeps track of it's components and can't do cycle in rails for obvious reasons. All in all id-based approach seems like a dead-end to me. I use "semi-unique" identifiers made from cell name and dom_id of the main object so it looks kind of like this:

<div class="calendar-day_1234">

This way I don't have to worry about updating the wrong fragment and if there are more than one - no problem.

@tortuetorche
Copy link

Sorry, I don't really understand what you said.
My English knowledge isn't as good as I hope.

If you use dom_id() helper, you can prefix it with comments:.

In a Rails console:

comment = Comment.first
helper.dom_id(comment)
=> "comment_2"
helper.dom_id(comment, 'comments:')
=> "comments:_comment_2"

The generated id is a bit weird, but it should work.

Then, when you run this Javascript command:

Turbolinks.replace('some HTML tags', {change: 'comments'});

Turbolinks will replace all the HTML nodes with an id beginning with this string: comments:.

@firedev
Copy link
Author

firedev commented Oct 7, 2015

I render the same fragment in a few places on the page, I can't generate #comments:comment_1:1 #comments:comment_1:2 #comments:comment_1:3. But if using css selectors, or even data-id one is good enough: .comments-comment_1.

Rails is going backwards here. Imagine each fragment is very expensive to compute, pre-rendederd and cached and I can't change id for each instance. What about russian-doll caching?

@tortuetorche
Copy link

Why do you render the same fragment in a few places of the page?

@firedev
Copy link
Author

firedev commented Oct 7, 2015

I am building a worktime calendar app, there are few stats cells on each end, there are day cells you can edit in a modal window and they are being updated on-the-fly.

Just remembers that this came up before and I was asking on StackOverflow: http://stackoverflow.com/questions/25418379/storing-object-id-in-html-document-id-vs-data-id-vs

Apparently there are cases when you want more than one kind of the same object on the page.

@tortuetorche
Copy link

Well, maybe you can do something like that:

class Comment < ActiveRecord::Base
  attr_accessor :context_id

  def to_key
    super << @context_id
  end
end

Where @context_id is the context of you record in the page.

@tortuetorche
Copy link

Or monkey patching the dom_id() helper to add a third argument, who appends a suffix.

comment = Comment.first
dom_id(comment, 'comments:', 1)
=> "comments:_comment_2_1"

@firedev firedev changed the title CSS class-based replace Selector-based replace Oct 8, 2015
@firedev
Copy link
Author

firedev commented Oct 8, 2015

I'll just rename the title to a more general 'selector-based' replacement, so it allows more freedom of speech.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants