phlex-ruby / phlex

A framework for building object-oriented views in Ruby.
https://beta.phlex.fun
MIT License
1.29k stars 84 forks source link

Turbo-stream seems (to me) to stop working about version 1.5.0/0.7.1-ish #588

Closed wdiechmann closed 1 year ago

wdiechmann commented 1 year ago

@joeldrapper you inquired in another issue whether I would elaborate on my observations regarding Turbo-streams. Here is the best I can do:

Etching my way towards latest versions of Phlex and Phlex-Rails

This is the output from 1.6.0 / 0.8.0

ActionView::Template::Error (undefined method `<<' for nil:NilClass

                                        @_target << output
                                                 ^^):

so that's as far as I go.

The 1.5.1 / 0.6.1 combo provides me with

ActionView::Template::Error ('#<Phlex::SVG:0x00000001169bc2a8>' is not an ActiveModel-compatible object. It must implement :to_partial_path.):

Going back to 1.4.0 / 0.7.1 has me back on solid ground 😄

Tiny steps forward to 1.5.1 / 0.7.1 (1.5.0 did the same thing) produces a screenshot shared as 1.5.1-0.7.1.png

1 5 1-0 7 1

I'm not able to produce the combination - but somewhere in the mix I observed a reasonably well functioning dashboard and lists - only when producing the form overlays
1 4 0-0 7 1 the screenshot above hopefully gives you an idea as to what I'm aiming at) I had to open the developer console and look at what came "down the wire" (which really does not compute at all with it all happening localhost-wise - anyways):


<turbo-stream action="replace" target="form_1"><template><div id="form_1" class="pointer-events-auto h-screen max-h-screen w-screen max-w-md"><form data-form-sleeve-target="form" id="form_1_innerform" enctype="multipart/form-data" class="scrollbar-hide h-full flex flex-col bg-white shadow-xl overflow-y-scroll " action="/equipment/26" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" autocomplete="off" /><input type="hidden" name="authenticity_token" value="XxcB69X9goVtR1azKOV_PUgJxkeFKlqRg3GzOL3Wh5oKf_bdzw13LRmSjWgzoC4TP10TYrtFPPM8rjiF33YjzQ" autocomplete="off" /> 

  <div class="sticky z-20 top-0 right-0 px-4 py-6 bg-gray-50 sm:px-6"><div class="flex items-start justify-between space-x-3"><div class="space-y-1"><h2 class="text-lg font-medium text-gray-900" id="slide-over-title"><span class="translation_missing" title="translation missing: da.equipment.form.edit">Edit</span></h2><p class="text-sm text-gray-500"><span class="translation_missing" title="translation missing: da.equipment.form.edit_description">Edit Description</span></p></div><div class="h-7 flex items-center"><button type="button" data-action="form-sleeve#cancel" class="text-gray-400 hover:text-gray-500"><span class="sr-only" sr="close form"></span><svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div></div>

  <!-- Divider container -->
  <div class="h-full py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">

    <!-- Name -->

    <!-- access_token -->

    <!-- mug_shot 
    <div class="px-4 pt-8 ">
      <div >
        <h3 class="text-lg leading-6 font-medium text-gray-900"><span class="translation_missing" title="translation missing: da.equipment.form.mug_shot">Mug Shot</span></h3>
        <p class="mt-1 max-w-2xl text-sm text-gray-500"><span class="translation_missing" title="translation missing: da.equipment.form.mug_shot_description">Mug Shot Description</span></p>
      </div>
    </div> -->

    <!-- state -->
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
      <div>
        <label for="state" class="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2">
          <span class="translation_missing" title="translation missing: da.equipment.form.state">State</span>
        </label>
      </div>
      <div class="sm:col-span-2 flex">
      </div>
    </div>

  </div>
  <div id="form-footer" class="fixed w-screen max-w-md bottom-0 w-full flex justify-start border-t border-gray-200 bg-gray-50 py-5 px-6 z-40"><div class="flex-none w-1/4 h-14"><a class="button delete-button" data-turbo-confirm="Are you sure?" data-turbo-method="delete" data-action="click-&gt;form-sleeve#toggle" href="/equipment/26">Slet</a></div><div class="flex justify-end w-full mr-5 sm:mr-1 md:mr-2"><div class="space-x-3"><span class="text-gray-400 text-xs" title="Equipment">26</span><button data-form-sleeve-target="cancel" data-action="click-&gt;form-sleeve#cancel" type="button" class="button cancel-button">Fortryd</button><button data-form-sleeve-target="save" type="submit" class="button save-button"><span class="group-disabled:hidden">Opdatér</span><span class="hidden group:disabled:block group-disabled:cursor-wait"><span class="translation_missing" title="translation missing: da.equipment.form.updating">Updating</span></span></button></div></div></div>
</form></div></template></turbo-stream>

The "gold standard" would look somewhat like this:

<turbo-stream action="replace" target="form_1"><template><div id="form_1" class="pointer-events-auto h-screen max-h-screen w-screen max-w-md"><form data-form-sleeve-target="form" id="form_1_innerform" enctype="multipart/form-data" class="scrollbar-hide h-full flex flex-col bg-white shadow-xl overflow-y-scroll " action="/equipment/25" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" autocomplete="off" /><input type="hidden" name="authenticity_token" value="YKXe7c9s_lO_Wo_q3MTmIRFCuPzAfCOE4N54XxF_BSb7IJrbng2WayPfZPNxmegZy9N3FLmBebVG3kXf9_4Uiw" autocomplete="off" /><input id="asset__account_id" name="asset[account_id]" focus="false" required="required" value="1" autocomplete="off" type="hidden" /><input id="asset__assetable_type" name="asset[assetable_type]" focus="false" required="required" value="Equipment" autocomplete="off" type="hidden" /><input id="asset_assetable_id" name="asset[assetable_attributes][id]" focus="false" required="required" value="25" autocomplete="off" type="hidden" /><div class="flex-1 relative space-y-12" data-controller="form" data-form-form-sleeve-outlet="#form-sleeve" data-form-list-outlet="#list" data-form-clipboard-prefix-value="https://localhost:3000/equipment/25" data-action="keydown-&gt;form#keydownHandler speicherMessage@window-&gt;form#handleMessages"><div class="border-b border-gray-900/10 pb-12 mb-14"> 

  <div class="sticky z-20 top-0 right-0 px-4 py-6 bg-gray-50 sm:px-6"><div class="flex items-start justify-between space-x-3"><div class="space-y-1"><h2 class="text-lg font-medium text-gray-900" id="slide-over-title"><span class="translation_missing" title="translation missing: da.equipment.form.edit">Edit</span></h2><p class="text-sm text-gray-500"><span class="translation_missing" title="translation missing: da.equipment.form.edit_description">Edit Description</span></p></div><div class="h-7 flex items-center"><button type="button" data-action="form-sleeve#cancel" class="text-gray-400 hover:text-gray-500"><span class="sr-only" sr="close form"></span><svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div></div>

  <!-- Divider container -->
  <div class="h-full py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">

    <!-- Name -->
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><label name="asset[name]" class="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2" data-action="click-&gt;form#fieldFaq" for="__Asset:0x000000010ba97368_name">Navn</label></div><div class="sm:col-span-2"><input id="asset__name" name="asset[name]" value="154" autocomplete="off" tabindex="0" required="required" data-form-target="focus" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>

    <!-- access_token -->
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5 "><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.access_token">access_token</span></div><div class="sm:col-span-2 flex"><input id="asset_assetable_access_token" name="asset[assetable_attributes][access_token]" value="o6V5d26noJkpuU3MncPHpaRn" disabled="disabled" tabindex="0" data-form-target="copytext" class="disabled w-full shrink shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md  }" type="text" /><button class="grow ml-1" type="button" data-action="form#copy_text" tabindex="0"><svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg></button><div class="text-sm text-red-800"></div></div><div class="col-start-2"><?xml version="1.0" standalone="yes"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="98" height="98" shape-rendering="crispEdges"><path d="M0 0h7v7h-7zM8 0h3v1h1v-1h2v2h3v1h-2v1h-1v-1h-1v-1h-3v-1h-1v1h-1zM15 0h1v1h-1zM18 0h1v1h-1zM20 0h2v1h-1v1h-1v1h2v-2h1v-1h2v1h-1v1h-1v2h4v1h2v2h-1v-1h-1v1h1v1h-1v1h-1v1h-2v-1h-1v1h-1v1h-1v1h-2v-2h2v-1h-1v-1h-1v1h-1v-1h-1v-1h-1v-1h1v1h1v-1h1v1h1v-2h-1v-1h-1v-1h1v-2h1zM27 0h4v1h-1v1h-1v-1h-2zM32 0h5v1h-1v2h-1v-2h-3zM40 0h1v3h-1v1h-1v-2h-2v-1h3zM42 0h7v7h-7zM1 1v5h5v-5zM25 1h1v1h-1zM31 1h1v1h1v2h-1v-1h-1zM43 1v5h5v-5zM2 2h3v3h-3zM9 2h1v1h-1zM27 2h1v1h-1zM44 2h3v3h-3zM8 3h1v2h1v-2h2v2h-2v1h-1v1h-1zM29 3h1v1h-1zM37 3h1v1h-1zM15 4h1v1h-1zM20 4v1h2v-1zM31 4h1v1h-1zM33 4h1v1h-1zM35 4h1v1h-1zM12 5h2v1h-1v2h-1v1h1v-1h1v-2h1v1h1v1h-2v1h-1v1h-4v-3h1v-1h1v1h-1v2h1v-2h1zM23 5v3h3v-3zM30 5h1v3h-1v1h-1v-2h1zM32 5h1v3h1v1h-2v2h-1v1h-1v-2h1v-2h1zM38 5h1v2h-1zM21 6v2h1v-2zM24 6h1v1h-1zM34 6h1v1h-1zM36 6h1v1h-1zM40 6h1v2h-1zM35 7h1v1h-1zM37 7h1v1h-1zM3 8h1v1h-1zM6 8h1v1h-1zM16 8h1v1h-1zM39 8h1v2h-1zM43 8h3v1h-1v1h1v1h-2v-1h-1zM47 8h2v3h-1v-2h-1zM0 9h1v1h-1zM2 9h1v1h-1zM5 9h1v1h-1zM7 9h1v1h-1zM14 9h1v1h-1zM17 9h1v1h-1zM27 9h1v1h1v2h-1v-1h-1v1h-2v-1h1v-1h1zM35 9h3v1h-2v2h1v-1h3v1h-1v1h-1v-1h-1v1h-2zM1 10h1v1h-1zM3 10h2v1h1v-1h1v1h-1v1h1v1h-2v1h-1v-1h-1zM8 10h1v4h1v1h-1v1h1v-1h1v-2h-1v-1h1v1h1v-2h1v-1h1v1h-1v1h1v2h-1v2h-1v1h-2v1h-1v-1h-1v-1h-1v-1h-1v1h1v1h-2v-1h-2v-1h-1v-1h2v1h1v-1h2v-1h1zM15 10h2v3h-2zM41 10h2v1h1v1h-1v1h-2zM33 11h1v1h-1zM47 11h1v1h-1zM0 12h2v1h-2zM18 12h1v1h-1zM22 12h1v1h-1zM24 12h1v4h1v-2h1v-1h2v-1h1v1h-1v1h-1v2h-2v1h1v1h-2v-1h-2v-1h-3v-2h3v-1h1zM31 12h1v1h-1zM44 12h3v1h2v2h-1v-1h-1v1h-1v2h1v-1h1v1h1v3h-1v-1h-1v1h-1v-2h-1v-1h-1v1h-1v1h-1v-1h-2v-1h3v-1h-1v-1h-1v-1h-1v1h-1v-2h2v1h1v1h1v-1h1v1h-1v1h1v-1h1v-2h-1zM17 13h1v1h-1zM30 13h1v1h-1zM32 13h1v1h-1zM34 13h1v1h-1zM37 13h1v1h-1zM0 14h1v1h-1zM14 14h3v1h-3zM23 14v2h1v-2zM29 14h1v1h1v-1h1v1h-1v1h-1v2h3v-1h-1v-1h1v-1h1v3h2v-1h-1v-3h2v1h1v1h-1v1h1v-1h1v4h2v-1h1v1h1v-1h2v1h-1v2h1v-2h1v2h1v-1h2v4h-1v-1h-1v-1h-2v1h1v1h-1v1h1v-1h2v1h-1v1h-4v2h1v-1h1v2h1v-2h1v-1h2v1h-1v1h1v2h-1v1h1v3h-1v1h1v3h-1v-1h-1v-4h1v-1h-1v-1h-1v-1h-3v1h-1v-2h-4v-1h2v-3h-1v-1h-1v-1h-1v1h-2v1h-1v-1h-1v-1h-1v1h-1v1h-1v1h-1v-1h-1v-1h1v-2h2v-2h-1v-1h3v-1h-4v-1h-1v-1h1zM40 15h1v1h-1zM1 16h1v1h-1zM15 16h2v1h-2zM18 16h2v1h2v2h-1v1h-1v-1h-1v-2h-1zM7 17h1v1h-1zM13 17h1v1h-1zM17 17h1v1h-1zM1 18h1v1h1v-1h1v1h-1v4h-1v1h-2v-3h1v1h1v-2h-1zM6 18h1v1h-1zM10 18h3v1h-3zM16 18h1v1h-1zM24 18h1v1h-1zM27 18h1v1h1v2h-1v2h-1v3h1v1h1v1h-1v3h-2v-1h1v-1h-1v-1h1v-1h-2v1h-2v-1h-1v2h1v3h-1v1h1v-1h2v-1h-1v-2h1v2h1v1h-1v1h-1v1h1v-1h1v-1h2v-1h4v-2h-1v1h-1v-1h-1v-1h1v-1h1v-1h1v-1h1v2h-2v1h3v-1h2v-1h1v4h-1v1h-1v-2h-2v2h-1v1h-2v1h1v1h-1v1h-1v1h1v2h2v-1h-1v-3h2v2h-1v1h3v-1h-1v-2h1v2h1v-2h1v-1h-2v-1h2v1h1v-1h1v1h-1v1h-1v1h1v1h-1v1h-1v1h1v-1h1v-1h1v1h-1v1h1v-1h1v-1h1v-1h-1v-1h1v1h1v-2h1v2h2v-1h1v3h-1v-1h-1v1h-1v1h2v6h1v-2h2v-2h-2v-1h2v1h1v3h-1v3h1v1h-2v-3h-1v1h-1v2h-1v-2h-1v1h-1v-1h-3v-1h-2v1h-1v-2h-2v-5h-1v3h-1v-2h-3v-2h-1v-3h-1v-1h-1v1h-1v1h2v2h1v3h-1v1h1v-1h1v1h-1v2h2v2h-1v-1h-2v4h-1v-1h-1v-1h1v-1h-3v2h1v2h-1v-1h-1v-1h-1v2h-1v-1h-1v1h-1v-1h-1v-1h-2v-1h-1v-1h1v-1h-3v1h-1v1h-1v-2h1v-1h1v-1h2v-1h-1v-1h-1v-1h-1v-1h2v-1h-3v1h-1v1h-4v-1h-3v1h2v1h-1v1h-3v-1h1v-2h-1v-1h1v-3h-1v-2h1v1h1v2h1v1h-1v1h1v-1h2v-3h-1v-2h-1v1h-1v-1h-2v-2h1v1h1v-2h2v-7h1v-1h-1v-1h2v1h1v-1h3v1h5v-1h1v1h1v-1h2v2h2v1h-1v1h1v-1h3v-1h1v-1h1v-1h1zM36 18v1h1v-1zM22 19h2v1h-1v1h-1zM17 20v2h-1v-1h-4v1h-1v-1h-2v1h1v1h-1v2h2v-1h-1v-1h1v1h1v-1h1v1h1v-2h1v2h-1v1h-3v1h5v-1h1v1h-1v2h-1v-1h-2v2h1v-1h1v4h-1v1h1v-1h1v4h-1v1h1v-1h1v-2h1v1h1v-1h2v-1h-4v-1h2v-1h-3v-1h4v-1h1v-2h-2v1h-1v1h-1v-3h5v-3h-1v2h-2v-1h-2v-1h2v-1h-1v-2zM35 20v1h-3v1h1v2h2v-1h-1v-1h1v-1h1v-1zM5 21v1h2v-1zM25 21v1h1v-1zM29 21h1v1h-1zM36 21v1h-1v1h1v-1h2v1h1v-1h2v-1zM42 21v1h1v-1zM5 23v3h3v-3zM23 23v3h3v-3zM39 23v2h1v-2zM41 23v3h3v-3zM2 24h1v1h-1zM6 24h1v1h-1zM24 24h1v1h-1zM42 24h1v1h-1zM1 25h1v1h-1zM2 26h1v1h-1zM9 26v1h1v-1zM38 26h1v2h-1zM5 27v2h1v-1h1v-1zM11 27v1h-2v2h-1v-2h-1v1h-1v1h1v1h-2v-1h-1v-1h-1v1h1v1h1v2h1v-1h2v-1h1v-1h1v-1h2v-2zM41 27v2h1v-2zM10 30v3h-1v-1h-1v1h-2v1h2v-1h1v2h-3v1h3v-1h1v-1h1v1h-1v1h1v-1h2v2h1v-2h1v-1h-3v-2h-1v-2zM12 30v2h1v-2zM33 31h1v1h-1zM40 31h1v2h-1zM3 33h1v1h-1zM21 34v1h-2v1h-2v1h1v1h-3v1h-1v-1h-1v1h1v1h1v1h1v-1h1v1h-1v1h-1v2h1v1h-1v1h1v-1h1v-2h1v2h-1v1h1v-1h1v-2h1v-1h1v1h-1v2h2v-1h-1v-1h1v-2h-1v-1h-2v-1h1v-1h1v2h2v-1h-1v-2h-1v-2h1v-1zM22 36v1h2v-1zM6 37v1h2v-1zM24 37v3h1v-3zM26 38v1h1v-1zM39 38v2h-1v-1h-1v1h1v1h-1v2h1v-1h1v-1h1v-1h2v-1h-2v-1zM9 39h1v1h1v1h-1v1h-2v-1h1zM43 39v1h1v-1zM6 40h1v1h-1zM18 40h1v1h-1zM23 41v3h3v-3zM29 41h2v1h-2zM35 41v1h1v-1zM41 41v3h3v-3zM0 42h7v7h-7zM24 42h1v1h-1zM42 42h1v1h-1zM1 43v5h5v-5zM32 43h1v1h-1zM2 44h3v3h-3zM31 44h1v1h-1zM34 44h1v1h-1zM8 45h1v1h-1zM12 45h1v1h-1zM28 45h1v1h1v-1h1v1h1v-1h1v1h-1v1h-1v1h-1v-1h-2zM34 46h1v2h1v-2h2v1h-1v1h1v1h-7v-1h2v-1h1zM9 47h1v1h-1zM14 47h1v1h-1zM41 47h1v1h-1zM43 47h1v2h-1zM45 47h1v2h-1zM10 48h1v1h-1zM12 48h2v1h-2zM25 48h1v1h-1zM27 48h2v1h-2zM40 48h1v1h-1zM47 48h2v1h-2z" fill="#333" transform="translate(0,0) scale(2)"/></svg></div></div>

    <!-- mug_shot 
    <div class="px-4 pt-8 ">
      <div >
        <h3 class="text-lg leading-6 font-medium text-gray-900"><span class="translation_missing" title="translation missing: da.equipment.form.mug_shot">Mug Shot</span></h3>
        <p class="mt-1 max-w-2xl text-sm text-gray-500"><span class="translation_missing" title="translation missing: da.equipment.form.mug_shot_description">Mug Shot Description</span></p>
      </div>
    </div> -->

    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.brand">brand</span></div><div class="sm:col-span-2"><input id="asset_assetable_brand" name="asset[assetable_attributes][brand]" value="54" autocomplete="off" tabindex="0" data-form-target="" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.model">model</span></div><div class="sm:col-span-2"><input id="asset_assetable_model" name="asset[assetable_attributes][model]" value="54" autocomplete="off" tabindex="0" data-form-target="" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>

    <div data-controller="combo" data-combo-resource-class-value="Asset" data-combo-current-value="ALCO" data-combo-lookup-class-value="Organization" data-combo-field-value="organization" data-combo-field-input-name-value="asset[assetable_attributes][organization_id]" data-combo-foreign-key-value="organization_id" data-combo-item-label-value="name" data-combo-lookup-label-value="name" data-combo-field-input-id-value="asset_assetable_organization_id" data-combo-is-list-value="false" data-combo-is-multi-value="false" data-combo-is-tags-value="false" data-combo-is-add-value="false" data-combo-is-search-value="true" data-combo-is-modal-value="false" data-combo-show-icon-value="false" data-combo-account-id-value="1" data-combo-new-arguments-value=":asset,[:account_id,:name,:assetable_type],:assetable,[:id,:name]" id="container_asset_assetable_organization_id" class="space-y-1 z-10 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.organization">organization</span></div><input id="asset_assetable_organization_id" name="asset[assetable_attributes][organization_id]" value="3" autocomplete="off" type="hidden" data-combo-target="selected" /><div class="relative mt-1 col-span-2"><div tabindex="0" id="taglist_asset_assetable_organization_id" data-combo-target="taglist" class="hidden relative flex flex-wrap flex-row m-1"><span data-combo-target="button" class="hidden"></span></div><input id="input_asset_assetable_organization_id" name="name_asset[assetable_attributes][organization_id]" tabindex="0" value="ALCO" autocomplete="off" type="text" class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-12 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm" role="combo" aria_controls="options" aria_expanded="false" data-form-target="" data-combo-target="input" data-action="blur-&gt;combo#leaveField focus-&gt;combo#enterField keydown-&gt;combo#keydownHandler keyup-&gt;combo#keyupHandler" /><button type="button" data-combo-target="button" tabindex="0" data-action="click-&gt;combo#clickIcon keydown-&gt;combo#keydownHandler" role="search" class="absolute inset-y-0 right-2 h-2 flex items-center pr-3 pt-3 rounded-r-md "><span class="w-2 h-2 justify-items-center text-gray-400 material-symbols-outlined">search</span></button><div class="hidden absolute top-10  scrollbar-hide inset-x-0 shadow-md rounded-md z-20  overflow-y-auto h-40 max-h-40 w-full" id="organization_combo_listwrapper" data-combo-target="selectOptions"><ul id="organization_ul" class="scrollbar-hide absolute h-40 max-h-40 z-20 my-1 justify-center w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black focus-visible:bg-indigo-600/5 ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" role="listbox" data-values="3" data-action="click-&gt;combo#clickListItem keydown-&gt;combo#keydownListHandler keyup-&gt;combo#keyupListHandler blur-&gt;combo#blurListHandler" aria-labelledby="listbox-label" aria-activedescendant="listbox-option-3"><li class="focus-visible:text-gray-500 focus:outline-none focus-visible:bg-gray-200 hover:bg-gray-200 text-gray-500 cursor-default select-none relative py-2 pl-3 pr-9" tabindex="0" data-record-id="3" data-resource-class="Organization" role="option"><span data-record-id="3" data-resource-class="Organization" class="font_normal block truncate">ALCO</span><span class="hidden text-indigo-600 absolute inset-y-0 right-0 flex items-center pr-4"><svg class="focus:text-white w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg></span></li></ul></div></div></div>
    <div data-controller="combo" data-combo-resource-class-value="Asset" data-combo-current-value="x silk" data-combo-lookup-class-value="Location" data-combo-field-value="location" data-combo-field-input-name-value="asset[assetable_attributes][location_id]" data-combo-foreign-key-value="location_id" data-combo-item-label-value="name" data-combo-lookup-label-value="name" data-combo-field-input-id-value="asset_assetable_location_id" data-combo-is-list-value="false" data-combo-is-multi-value="false" data-combo-is-tags-value="false" data-combo-is-add-value="false" data-combo-is-search-value="true" data-combo-is-modal-value="false" data-combo-show-icon-value="false" data-combo-account-id-value="1" data-combo-new-arguments-value=":asset,[:account_id,:name,:assetable_type],:assetable,[:id,:name]" id="container_asset_assetable_location_id" class="space-y-1 z-10 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.location">location</span></div><input id="asset_assetable_location_id" name="asset[assetable_attributes][location_id]" value="88" autocomplete="off" type="hidden" data-combo-target="selected" /><div class="relative mt-1 col-span-2"><div tabindex="0" id="taglist_asset_assetable_location_id" data-combo-target="taglist" class="hidden relative flex flex-wrap flex-row m-1"><span data-combo-target="button" class="hidden"></span></div><input id="input_asset_assetable_location_id" name="name_asset[assetable_attributes][location_id]" tabindex="0" value="x silk" autocomplete="off" type="text" class="w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-12 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm" role="combo" aria_controls="options" aria_expanded="false" data-form-target="" data-combo-target="input" data-action="blur-&gt;combo#leaveField focus-&gt;combo#enterField keydown-&gt;combo#keydownHandler keyup-&gt;combo#keyupHandler" /><button type="button" data-combo-target="button" tabindex="0" data-action="click-&gt;combo#clickIcon keydown-&gt;combo#keydownHandler" role="search" class="absolute inset-y-0 right-2 h-2 flex items-center pr-3 pt-3 rounded-r-md "><span class="w-2 h-2 justify-items-center text-gray-400 material-symbols-outlined">search</span></button><div class="hidden absolute top-10  scrollbar-hide inset-x-0 shadow-md rounded-md z-20  overflow-y-auto h-40 max-h-40 w-full" id="location_combo_listwrapper" data-combo-target="selectOptions"><ul id="location_ul" class="scrollbar-hide absolute h-40 max-h-40 z-20 my-1 justify-center w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black focus-visible:bg-indigo-600/5 ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" role="listbox" data-values="88" data-action="click-&gt;combo#clickListItem keydown-&gt;combo#keydownListHandler keyup-&gt;combo#keyupListHandler blur-&gt;combo#blurListHandler" aria-labelledby="listbox-label" aria-activedescendant="listbox-option-3"><li class="focus-visible:text-gray-500 focus:outline-none focus-visible:bg-gray-200 hover:bg-gray-200 text-gray-500 cursor-default select-none relative py-2 pl-3 pr-9" tabindex="0" data-record-id="88" data-resource-class="Location" role="option"><span data-record-id="88" data-resource-class="Location" class="font_normal block truncate">x silk</span><span class="hidden text-indigo-600 absolute inset-y-0 right-0 flex items-center pr-4"><svg class="focus:text-white w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg></span></li></ul></div></div></div>

    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5 "><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.purchased_at">purchased_at</span></div><div class="sm:col-span-2"><input id="asset_assetable_purchased_at" name="asset[assetable_attributes][purchased_at]" value="2021-01-01T01:01:00" data-form-target="" tabindex="0" step="60" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md }" type="datetime-local" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.purchase_price">purchase_price</span></div><div class="sm:col-span-2"><input id="asset_assetable_purchase_price" name="asset[assetable_attributes][purchase_price]" value="54" autocomplete="off" tabindex="0" data-form-target="" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.residual_value">residual_value</span></div><div class="sm:col-span-2"><input id="asset_assetable_residual_value" name="asset[assetable_attributes][residual_value]" value="54" autocomplete="off" tabindex="0" data-form-target="" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5 "><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.warranty_ends_at">warranty_ends_at</span></div><div class="sm:col-span-2"><input id="asset_assetable_warranty_ends_at" name="asset[assetable_attributes][warranty_ends_at]" data-form-target="" tabindex="0" step="60" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md }" type="datetime-local" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class=""><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.serial_number">serial_number</span></div><div class="sm:col-span-2"><input id="asset_assetable_serial_number" name="asset[assetable_attributes][serial_number]" value="54" autocomplete="off" tabindex="0" data-form-target="" type="text" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md" /><div class="text-sm text-red-800"></div></div></div>
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5"><div class="col-span-3"><span class="translation_missing" title="Translation missing: da.activerecord.attributes.equipment.description">description</span></div><div class="col-span-3"><textarea id="asset_assetable_description" name="asset[assetable_attributes][description]" tabindex="0" rows="5" data-form-target="" placeholder="" class="block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md }">
sdfghj dfghj</textarea><div class="text-sm text-red-800"></div></div></div>

    <!-- state -->
    <div class="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
      <div>
        <label for="state" class="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2">
          <span class="translation_missing" title="translation missing: da.equipment.form.state">State</span>
        </label>
      </div>
      <div class="sm:col-span-2 flex">
      </div>
    </div>

  </div>
  <div id="form-footer" class="fixed w-screen max-w-md bottom-0 w-full flex justify-start border-t border-gray-200 bg-gray-50 py-5 px-6 z-40"><div class="flex-none w-1/4 h-14"><a class="button delete-button" data-turbo-confirm="Are you sure?" data-turbo-method="delete" data-action="click-&gt;form-sleeve#toggle" href="/equipment/25">Slet</a></div><div class="flex justify-end w-full mr-5 sm:mr-1 md:mr-2"><div class="space-x-3"><span class="text-gray-400 text-xs" title="Equipment">25</span><button data-form-sleeve-target="cancel" data-action="click-&gt;form-sleeve#cancel" type="button" class="button cancel-button">Fortryd</button><button data-form-sleeve-target="save" type="submit" class="button save-button"><span class="group-disabled:hidden">Opdatér</span><span class="hidden group:disabled:block group-disabled:cursor-wait"><span class="translation_missing" title="translation missing: da.equipment.form.updating">Updating</span></span></button></div></div></div>
</div></div></form></div></template></turbo-stream>
joeldrapper commented 1 year ago

What's the controller code that's rendering the turbo stream? The @_target being nil is strange and it sounds like an incompatibility between phlex and phlex-rails. There were a few times when phlex and phlex-rails were updated at the same time with breaking changes between them. It's best to have only phlex-rails in your Gemfile and let it pick the compatible version of phlex.

joeldrapper commented 1 year ago

If you’re upgrading, I recommend jumping to the latest version of phlex-rails and letting it find the latest version of phlex. Then fix each issue one-by-one. There's no need to go version-by-version, as you're likely to run into bugs that were already fixed.

All the breaking changes should have been documented in the release notes.

A lot of these can be fixed with simple find and replace. For example, the change from text to plain should be quite simple when you know it's coming. We had to rename this in order to support SVGs which have a text element. https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text

wdiechmann commented 1 year ago

What's the controller code that's rendering the turbo stream?

Well, like they say in Hollywood: it's complicated mostly because I use a lot of OO-ing and DRY-ing to keep down the LOC 😆 (incidentally that is why I am head over heels into Phlex too!)

- but where Rails sort-a leaves it off to me, things start (leaving out routes.rb) here

# controllers/abstract_resources_controller.rb
    def edit_resource
      lockable? ? 
         render( turbo_stream: turbo_stream.replace( resource_form, partial: 'form', locals: { resource: resource } ) ) :
         lock_warning
    end

There's a little helper in there

# helpers/resources_helper.rb
  def resource_form rs=nil
    return ("form_%s" % (Current.user.id rescue '0')) if rs.nil?
    "%s_%s_form" % [rs.class.to_s.underscore, (Current.user.id rescue 'new')]
  end

and a concern dealing with actually finding data

# controllers/concerns/resource_control.rb
  #
  # resource is divided into 2 main categories
  #
  # * 4 core resources from which a majority of resources are delegated_from
  # * other resources like dashboards, roles, profiles, and other supporting resources
  #
  # the 4 core resources are Event, Message, Participant, Asset
  # in which case calling for a resource will return the core resource
  # provided the action is one of 'new' 'edit', 'create', 'update', 'destroy', more
  #
  def resource
    @resource ||= fixate_resource
  end

  def fixate_resource
    r = (_id.nil? ? new_resource : resource_class.find(_id) )
    r = r.delegated_from if (r.respond_to? :delegated_from) && ( %w( new edit create update destroy clonez wizard release_lock ).include? params[:action] )
    params[:action]=="clonez" ? r.clone_from : r
  end

The meat so to speak is in the _form.html.erb (which I took the liberty of tersening* [leaving out multiple input fields performing likewise] to improving readability, and shortening the already way to long comment!!)

# views/equipment/_form.html.erb
<%= render_form( resource: resource, assoc: :assetable ) do |form| %> 

  <%= render_form_header( resource: resource, title: form_header_title, description: form_header_description ) %>
  <%= render_form_errors(resource: resource) if resource.errors.size > 0 %>

  <!-- Divider container -->
  <div class="h-full py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">

    <!-- Name -->
    <%= form.text_field( :name, required: true, focus: true, input_css: "block w-full shadow-sm sm:text-sm focus:ring-indigo-500 focus:border-indigo-500 border-gray-300 rounded-md") %>

    <!-- access_token -->
    <%= form.token_field( :access_token, assoc: :assetable) %>

   ---8<---

  </div>
  <%= render_form_action_buttons resource: resource, delete_url: resource_url(), deleteable: !resource.new_record? %>
<% end %>

Another helper sneaked in

# helpers/view_components_helper.rb

  def render_form(**attribs, &block)
    attribs[:action] ||= params[:action]
    render Views::Components::Form::Form.new **attribs, &block
  end

As for the rest of the journey – I've had a small blog post laying dormant and now seemed like a proper occasion to publish it and reveal my arteries 😢

It's best to have only phlex-rails in your Gemfile and let it pick the compatible version of phlex.

Sure, that's my general MO but when I stumbled over the to_str vs to_s issue in my own unelegant way I started looking for a ways out, obviously to no greater avale

If you’re upgrading, I recommend jumping to the latest version of phlex-rails and letting it find the latest version of phlex.

Yeah - like I said, that's when sh*t hit the fan, metaphorically speaking 😉

A lot of these can be fixed with simple find and replace. For example, the change from text to plain should be quite simple when you know it's coming. We had to rename this in order to support SVGs which have a text element. https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text

(and) I understand and I was way out of order (but a moments brain fart had me ventilate all sorts of no-so-niceties which is a HUGE turn-off and something I cannot recall when I did last if ever, knowingly that is) - and I would like to take this opportunity to once again apologise! It was not cool!


* I know it's not a word, but if you can 'sweetening' something I cannot see why not tersening 😆

joeldrapper commented 1 year ago

I can’t quite follow all this code, but it doesn’t look right to me. To render a turbo stream, you should do something like this.

render turbo_stream.replace("some_id", SomeComponent.new(arguments, here))

There's no need for partial: or locals: arguments. That's what you use if you're rendering an ERB partial.

wdiechmann commented 1 year ago

once the transition is complete I aim to do just that - but for now I need to allow for rendering both ways (the traditional 'partial' way - and using Phlex) hence the partial - that just calls the view_helper in turn calling the component

wdiechmann commented 1 year ago

i guess this is as far as we go on this issue - will close it with 🤞

maybe some future version will not throw errors like:

ActionView::Template::Error (undefined method `<<' for nil:NilClass

and

ActionView::Template::Error (undefined method `to_str' for Location:Class
joeldrapper commented 1 year ago

The first error is because of incompatible versions of phlex and phlex-rails. What's happening is phlex-rails is trying to append something to the @_target buffer. But that buffer was moved to a new context object in phlex. phlex-rails was updated to support this, but you need to use the update if you're going to use the later version of phlex.

We simply can't make it so that you can use any version of phlex-rails with any version of phlex; we'd never be able to add features to either of them.

The second error is being addressed by #569