0

I've searched through the hotwire docs and I know that I can pass target value to "_top" to make full page reload. But I need some elegant way to do this. Let's say i have on the every page selectbox where user can pick account under which he will work within the system. Selectbox returning as a value account id. So my endpoints are nested under accounts eg. /accounts/:account_id/some_path ...

Now let's say user is on the /accounts/5/some_path and then pick from the select box account with id 4. Now what I want to achieve is that user will remain on the current page just need to update account id in url and the whole content of the current page. Is there a way to do this with hotwire?

Note: some_path can be every endpoint nested under accounts

Note2: in selectbox is also option to create new account which can access accounts/new endpoint

<%= form_with(model: user, local: true) do |form| %>
  <%= form.select(:account_id, user.accounts.collect { |p| [p.name, p.id] } + [['New account', 'new']], { :prompt => "Select account" }, onchange: 'location.href=document.getElementById("user_account_id").value') %>
<% end %>

I try this but I think Hotwire is able to do this also... unfortunately I'm newbie with hotwire so appreciate any help...

Holger Just
  • 52,918
  • 14
  • 115
  • 123
  • 1
    rails provide with form submit to refresh the page, all depends you wants, can set javascript event to select control to force submit form – Enrique YC Feb 27 '23 at 18:39

1 Answers1

0

So after a few hours a figured it. Firstly I created stimulus controller best way to do this is with rails generator rails g stimulus <name> because of it automatically adds your new stimulus controller to index.js file. Now my stimulus controller looks like:

import {Controller} from "@hotwired/stimulus"

export default class extends Controller {
    static targets = ["anchor"]
    get_current_url() {
        const {
            host, hostname, href, origin, pathname, port, protocol, search
        } = window.location
        return pathname
    }

    changeWorkingAccount(event) {
        const selectedOption = event.target.value;
        if (selectedOption == "new") {
            this.anchorTarget.href = "/new"
        } else {
            let path = this.get_current_url()
            let str = path.split("/").filter(n => n)
            str[0] = selectedOption
            let new_path = "/"
            str.forEach(element => new_path += element + "/");
            this.anchorTarget.href = new_path
        }
        this.anchorTarget.click()
    }
}

Secondly, I connected my form with stimulus controller and add empty anchor element.

<div data-controller="account-scope">
  <%= form_with(model: user, local: true, data:{account_scope_target: :accountSelect,
                                                :action=>"change->account-scope#changeWorkingAccount"}) do |form| %>
    <%= form.select(:account_id, user.accounts.collect { |p| [p.name, p.id] } + [['New account', 'new']], { :prompt => 1 }) %>
  <% end %>

  <a href="#" data-turbo-frame="_top" data-account-scope-target="anchor"></a>
</div>

So now, onchange is triggered changeWorkingAccount method where I just take selected option and create my custom desired path then this path is set to anchor href attribute and just simply call click function on the anchor and this works for me.