hotwired/turbo-rails

Add morph to StreamActions

cavenk opened this issue · 5 comments

Hi,

Is it possible to update the javascript assets 'turbo.js' to have the morph action into StreamActions?
The turbo library already have the code but the assets file 'turbo.js' doesn't have the morph action.

Thanks

I'm a bit confused. According to the turbo handbook, morphing can be performed with the replace action:

<turbo-stream action="replace" method="morph" target="current_step">
  <template>
    <!-- The contents of this template will replace the element with ID "current_step" via morph. -->
    <li>New item</li>
  </template>
</turbo-stream>

However, turbo-rails on 2.0.6 currently ignores the morph argument altogether. This call

turbo_stream.replace "clearance_5", method: "morph"

results in

<turbo-stream action="replace" target="clearance_5">

However, morph support seems to be present in this gem, although as an action. This call

turbo_stream.morph "clearance_5"

results in

<turbo-stream action="morph" target="clearance_5">

which throws an JS exception on turbo 8.0.5: Error: <turbo-stream action="morph" target="clearance_5">: unknown action

Is this an oversight and turbo_stream.morph should result in action="replace" method="morph" instead?

I think is an issue here :)

the update has an if method == 'morph' https://github.com/hotwired/turbo/blob/main/src/core/streams/stream_actions.js#L39-L50
same for replace: https://github.com/hotwired/turbo/blob/main/src/core/streams/stream_actions.js#L27-L37

idiot code

 def morph(target, content = nil, **rendering, &block)
    action :update, target, content, method: "morph", **rendering, &block
  end
def turbo_stream_action_tag(action, target: nil, targets: nil, template: nil, method: nil)
  template = action.to_sym.in?([:remove, :refresh]) ? "" : tag.template(template.to_s.html_safe)

  attributes = { action: action }
  attributes[:target] = convert_to_turbo_stream_dom_id(target) if target
  attributes[:targets] = convert_to_turbo_stream_dom_id(targets) if targets
  attributes[:method] = method if method

  tag.turbo_stream(**attributes) { template }
end
def action(name, target, content = nil, allow_inferred_rendering: true, method: nil, **rendering, &block)
  template = render_template(target, content, allow_inferred_rendering: allow_inferred_rendering, **rendering, &block)

  attributes = { target: target, template: template }
  attributes[:method] = method if method

  turbo_stream_action_tag name, **attributes
end

and the response will be

<turbo-stream action="update" target="some id" method="morph"><template>  
    html content
</template></turbo-stream>

just a hack :)

code here: https://github.com/hotwired/turbo-rails/pull/651/files

Instead of a morph action Turbo now supports a method=morph attribute in the existing actions. See https://turbo.hotwired.dev/reference/streams.

@jorgemanrubia

However, turbo-rails on 2.0.6 currently ignores the morph argument altogether. This call

turbo_stream.replace "clearance_5", method: "morph"

results in
<turbo-stream action="replace" target="clearance_5">

@AlexKovynev nice catch!
@jorgemanrubia it appears that the attributes arg is only passed from the broadcast tag builders, I updated the model tag builders for replace and update actions to pass the same arg
#658