# Turbo Drag and Drop: Part 2 - Refactor Turbo Frames

In the [previous post](https://code.avi.nyc/turbo-forms-drag-and-drop-in-ruby-on-rails-part-1) we built a common UI pattern of a button that reveals a form and on submitting the form, adds the newly created item to a list. We implemented the new playlist functionality using Turbo Frames and just a little bit of Javascript to handle interactions such as focusing the field and removing the new form after submission. We accomplished this with inline Javascript, which I thought was a harmless good idea. As a few pointed out, [CSP (Content Security Policy)](developer.mozilla.org/en-us/docs/web/http/csp) restrictions may block inline scripts.

[Dom Christie](https://twitter.com/domchristie) was nice enough to [refactor my code](https://github.com/domchristie/turbo-drag-and-drop/compare/main...domchristie:turbo-drag-and-drop:playlists_frame) to use just Turbo Frames and I thought I would go over the refactor in this quick part 2 before we move onto the actual drag and drop functionality.

The key change is wrapping the entire sidebar in a turbo frame that can be reloaded on each interaction.

![Turbo Frame](https://img.avi.nyc/7WlkHjvr+)

Just so I understand it, I want to break down how it works.

On the initial page load, a partial, [`playlists/playlists`](https://github.com/aviflombaum/turbo-drag-and-drop/blob/743a410a013b811fbe5ec6de437ca8193720f928/app/views/playlists/_playlists.html.erb) loads that contains the entire sidebar wrapped in a turbo frame `playlists`.

This ensures that any interaction within this frame will re-render the frame if the response contains a `playlists` turbo frame.

The first interaction is clicking on the "Add" Playlist button to load the new playlist form. Clicking on the button triggers a request to `/playlists/new`, or `playlists#new` which re-renders the `playlists/playlists` partial with just one change, [a really clever use of blocks to include the new playlist form.](https://github.com/aviflombaum/turbo-drag-and-drop/blob/743a410a013b811fbe5ec6de437ca8193720f928/app/views/playlists/new.html.erb#L2)

```erb
<%= render "playlists/playlists" do %>
  <div class="px-3"><%= render "form" %></div>
<% end %>
```

By including a block to the `render` call, any content passed to the block will be rendered in the position of the a `yield` statement within that partial. This allows the form to be rendered on top of the list of playlists.

[`playlists/_playlists.html.erb`](https://github.com/aviflombaum/turbo-drag-and-drop/blob/743a410a013b811fbe5ec6de437ca8193720f928/app/views/playlists/_playlists.html.erb#L10)
```erb
<%= turbo_frame_tag "playlists" do %>
  <div class="space-y-4">
    <div>
      <div class="flex justify-between items-center pl-6 pr-3">
        <h2 class="relative text-lg font-semibold tracking-tight">Playlists</h2>
        <%= render_button as: :link, href: new_playlist_path, variant: :ghost, class: "px-2" do %>
          + Add
        <% end %>
      </div>
      <%= yield %>
      <div dir="ltr" class="relative px-1">
        <div class="h-full w-full rounded-[inherit]">
          <div style="min-width: 100%; display: table">
            <div data-controller="playlists">
              <%= render collection: Playlist.all, partial: "playlists/playlist" %>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
<% end %>
```

Since the initial call to `playlists/playlists` when we first loaded the page included no block, this partial rendered the frame without the new playlists form. But when we click that button and re-render `playlists/playlists` in the context of `playlists#new`, because we're passing a call to render the block when we render the `playlists/playlists` partial, the form will appear.

All this will happen without a page reload and any javascript because that's how turbo frames work.

In the same way, when the new form is submitted within the `playlists` turbo frame, if the response contains a `playlists` turbo frame, the frame will be re-rendered without a page reload.

Sure enough, if we look at `playlists#create`, it redirects to `playlists/index`, which just re-renders `playlists/playlists` and the `playlists` turbo frame. When a the new playlist form is submitted, re-rendering the `playlists/playlists` partial will now contain the playlist that was just created.

That's the gist of the refactor. It's way more elegant, doesn't include any javascript, and doesn't violate any CSP.

