賞金將在 5 天后到期。此問題的答案有資格獲得 100聲望賞金。 zdebyman希望引起對這個問題的更多關注。
我有 rails 7 應用程式,我正在嘗試使用tom-select或slim-select構建搜索欄。無論我使用哪個庫,我的問題都會重現,因此它一定是我的問題所在。
應用程式/視圖/城市/index.html.erb
<%= form_for :city, url: cities_path, method: 'GET' do |f| %>
<div class="mt-4 border bg-light px-4 py-3 rounded-3">
<%= f.select :search_city, [], {},
placeholder: 'Type to search',
data: {
controller: 'ts--search',
ts__search_url_value: autocomplete_cities_path
} %>
<%= f.submit 'Search', class: 'btn mx-auto' %>
</div>
<% end %>
這是我的 js 控制器(在這種情況下,我使用的是 tom-select) app/javascript/controllers/ts/search_controller.js
import { Controller } from "@hotwired/stimulus";
import { get } from "@rails/request.js";
import TomSelect from "tom-select";
export default class extends Controller {
static values = { url: String };
connect() {
var config = {
plugins: ["input_autogrow", "remove_button", "no_active_items"],
render: {
option: this.render_option,
item: this.render_option,
},
valueField: "value",
loadThrottle: 400,
load: (q, callback) => this.search(q, callback),
closeAfterSelect: true,
persist: false,
create: false,
delimiter: ", ",
maxItems: 10,
};
new TomSelect(this.element, config);
}
async search(q, callback) {
const response = await get(this.urlValue, {
query: { query: q },
responseKind: "json",
});
if (response.ok) {
callback(await response.json);
} else {
console.log("Error in search_ctrl: ");
callback();
}
}
render_option(data, escape) {
return `<div>${escape(data.text)}</div>`;
}
}
應用程式/控制器/cities_controller.rb
class CitiesController < ApplicationController
def index
end
def autocomplete
list = City.order(:name)
.where("name ilike :q", q: "%#{params[:q]}%")
render json: list.map { |u| { text: u.name, value: u.id, sub: u.state } }
end
end
問題重現:
- 打開城市索引并點擊搜索欄。
- 下拉選單打開,我可以輸入并選擇一個建議。選擇后,建議會出現在搜索欄中,單擊“x”會將其從搜索欄中洗掉。
- 我添加任意數量的搜索令牌,1-N。
- 單擊“搜索”-> 查看結果頁面。
- 單擊瀏覽器中的后退按鈕(或在手機上滑動)
預期行為:搜索欄與搜索前完全相同。單擊“x”會洗掉令牌。單擊搜索欄允許輸入搜索查詢并添加更多令牌。
實際行為:我可以看到令牌,但是單擊“搜索”按鈕以外的任何內容都沒有執行任何操作。我可以在 this one和 this one這樣的多個演示中看到相同的行為。
回來后如何讓JS作業?
uj5u.com熱心網友回復:
// TLDR
// app/javascript/controllers/ts/search_controller.js
disconnect() {
this.element.tomselect.destroy();
}
當使用瀏覽器“后退按鈕”時,Turbo Drive會進行恢復訪問并顯示頁面的快取副本。此副本在訪問另一個頁面之前保存。任何附加的 javascript 行為都會丟失,我們只得到 html。
當Stimulus連接到[data-controller=ts--search]時,選擇元素由TomSelect修改:
<select placeholder="Type to search" data-controller="ts--search" data-ts--search-url-value="/cities/autocomplete" name="city[search_city]" id="city_search_city">
</select>
對此:
<select placeholder="Type to search" data-controller="ts--search" data-ts--search-url-value="/cities/autocomplete" name="city[search_city]" id="city_search_city"
multiple="multiple"
tabindex="-1"
class="tomselected ts-hidden-accessible">
<!-- ^
NOTE: this class
-->
</select>
<div class="ts-wrapper multi plugin-input_autogrow plugin-remove_button plugin-no_active_items has-options">
<!-- ... -->
</div>
單擊另一個鏈接時,此修改后的 html 將保存到快取中,稍后在使用瀏覽器后退導航時恢復。然后Stimulus再次連接,但是,TomSelect跳過.tomselected元素以避免再次附加.ts-wrapper。它看起來是一樣的,因為加載了 html 和樣式,但沒有附加 javascript 行為。
我們可以通過打開Stimulus除錯日志來獲得更多背景關系:
// app/javascript/controllers/application.js
application.debug = true // <= set this to `true`
// app/javascript/controllers/ts/search_controller.js
// inside connect()
console.log(this.element.getAttribute("class"));
new TomSelect(this.element, config);
console.log(this.element.getAttribute("class"));
如果帶有搜索表單的頁面被快取并且我們通過單擊鏈接導航到它:
// a cached page is displayed while
// waiting for response from the server
ts--search #initialize // found ts--search on the page
tomselected ts-hidden-accessible // cached <select>
// new TomSelect() has no effect
tomselected ts-hidden-accessible // at least it looks the same
ts--search #connect // finished connecting
// a fresh response from the server arrived
ts--search #disconnect // <= SOLUTION
ts--search #initialize // run the lifecycle again on a new page
null // untouched <select> from the server
// new TomSelect() now works
tomselected ts-hidden-accessible // new fancy select is on the page
ts--search #connect // done
使用瀏覽器后退導航時:
// a cached page is displayed
ts--search #initialize // found ts--search on the page
tomselected ts-hidden-accessible // cached <select>
tomselected ts-hidden-accessible // new TomSelect() does nothing
ts--search #connect // fail
離開我們的表單時還會發生另一件事(通過單擊離開、瀏覽器回傳或瀏覽器前進):
before-cache
ts--search #disconnect
在頁面被Turbo快取之前,Stimulusdisconnect()在我們的搜索控制器中呼叫。我們可以在這里恢復原來的選擇,在turbo快取頁面之前。這樣,TomSelect可以在快取頁面上重新應用。
// app/javascript/controllers/ts/search_controller.js
disconnect() {
this.element.tomselect.destroy();
}
https://turbo.hotwired.dev/handbook/drive#restoration-visits
https://turbo.hotwired.dev/handbook/building#understanding-caching
https://stimulus.hotwired.dev/reference/lifecycle-callbacks#disconnection
https://tom-select.js.org/docs/api/#destroy
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/498039.html
標籤:javascript 轨道上的红宝石 ruby-on-rails-7 苗条选择 汤姆选择
下一篇:捆綁安裝運行兩次
