В моем приложении Svelte есть раскрывающееся меню, в котором отображается список игроков. Я хочу иметь возможность искать игрока в этом списке и чтобы в раскрывающемся меню отображались только те игроки, которые соответствуют поисковому запросу. Однако, когда в списке есть только один подходящий игрок, я не могу выбрать (обновить) этого игрока из раскрывающегося меню; но в выпадающем меню отображается один игрок. Как я могу решить эту проблему?
Выбирать
<select class = "form-select" bind:value = {player_id} id = "player">
{#each players as player}
{#if !tournament.players.includes(player._id) && player.name
.toLowerCase()
.includes(searchTerm.toLowerCase())}
<option value = {player._id}>{player.name}</option>
{/if}
{/each}
</select>
Панель поиска
<input class = "rounded line"
type = "text"
bind:value = {searchTerm}
placeholder = "Search for a player"
/>
Кнопка обновления
<button class = "btn btn-primary line"
on:click = {addPlayerToTournament}>Update
</button>
ОБНОВЛЕНО Функция addPlayertoTournament
function addPlayerToTournament() {
tournament.players.push(player_id);
tournament.players = tournament.players;
axios
.put(
"http://localhost:3001/api/tournaments/" + tournament_id,
tournament
)
.then((response) => {
getTournament();
});
}
Я попытался использовать функцию include, чтобы проверить, включено ли имя игрока в поисковый запрос, а затем использовать оператор if, чтобы показать в раскрывающемся меню только тех игроков, которые соответствуют этому условию.
Я был бы признателен за любую помощь или предложения о том, как решить эту проблему.
Если вы попытаетесь зарегистрировать идентификатор игрока в функции addPlayerToTournament, вы получите значение? Похоже, проблема может быть связана с тем, что элемент select не имеет значения по умолчанию. Вы можете добавить опцию «отключено» с текстом «пожалуйста, выберите игрока» или использовать {# each players as player, i }, чтобы выбрать первый элемент, если i == 0.
Я провел небольшое тестирование в Svelte REPL, допустим, у вас есть два игрока. Когда вы добавляете первого игрока, скажем, Джона, id = 1, для выбора остается один вариант - игрок 2. Но player_id не меняется, он по-прежнему содержит идентификатор Джона. Я не уверен, что это самый элегантный способ решить эту проблему с помощью Svelte, но вы можете добавить значение по умолчанию, как предложил @Jelmer, или самостоятельно обработать player_id в функции addPlayerToTournament.
спасибо всем за ваши предложения :) у меня работает по умолчанию, но единственная проблема в том, что значение по умолчанию не показывает мне предложение поиска. Какие-нибудь советы? Если я удалю свой поисковый ввод, предложение на панели выбора всегда будет именем игрока. + Я работаю с кодом, предоставленным @Jelmer ({# each players as player, i }и i == 0.
Можете ли вы показать это в Repl?
@Corrl Я новичок, поэтому не уверен, что такое Repl. Могу ли я использовать replit и скопировать туда код? Вам нужен веб-просмотр? Спасибо за ваше время.
Это Repl svelte.dev/repl/hello-world?version=3.55.0 Не могли бы вы сделать пример, показывающий вашу проблему?
@Corrl Я старался изо всех сил, но не могу восстановить свою проблему. Вот ссылка на код ссылка и позвольте мне кое-что объяснить. Здесь я могу ввести игрока, и он появится на панели выбора, но когда я сделаю то же самое в своем проекте, он покажет значение по умолчанию («пожалуйста, выберите игрока»). Может быть, это как-то связано с моей БД? или Функция? Еще раз спасибо за ваше время, я очень ценю это.
Боюсь, не видя кода, который не работает, его сложно отлаживать...
Играя с этим в Repl, я думаю, что даже если это может выглядеть так, как будто оно работает (видимые параметры меняются при поиске), значение, которое отправляется при обновлении, неверно. Отправка «Боба» или «Чарли» через поиск будет регистрироваться [1, 1], поэтому было добавлено начальное значение let player_id = 1;. Вот один из способов, как может работать логика svelte.dev/repl/11d4781c8c9d41ed88688b883456d3e5?version=3.55.0
@Corrl Спасибо за ваш ответ, но я столкнулся с двумя проблемами с этим кодом, который вы предоставили. 1. Если я наберу C и выберу Czzz в качестве опции, Чарли отправится на турнир. 2. И из-за кода .push() и tournament.players = [...tournament.players, player_id] игрок будет отправлен на турнир два раза (поэтому, если я не прав, я могу использовать только один из них). извините за неудобства.
.push()плюс присваивание или строка оператора распространения не вместе, это альтернативные способы изменения массива. Насчет другого не уверен, посмотрю...
Хорошо, проблема заключалась в том, что при изменении player_id выполнялась функция, которая вычисляла массив внутри цикла #each. Я сделал Repl, чтобы проверить поведение svelte.dev/repl/220e5ef265ad4579996ab2529649da1c?version=3.55.0 и обновил последнюю ссылку новой версией, которая, я думаю, теперь работает правильно
Давайте продолжим обсуждение в чате.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я хотел поблагодарить пользователя @Corrl за всю его помощь и усилия по предоставлению рабочего решения. Теперь я могу двигаться вперед с моим проектом, и я очень благодарен за их вклад. Я приложил решение, которое в итоге сработало для меня, дайте мне знать, если у вас есть какие-либо вопросы.
Кодовый блок
<script>
let searchTerm = "";
let selectablePlayers = [];
$: calculateSelectablePlayers(searchTerm, tournament)
function calculateSelectablePlayers(searchTerm, tournament) {
console.info('calculate - only runs if searchTerm or tournament changes')
if (searchTerm || tournament.players.length > 0) {
selectablePlayers = players.filter(player => {
const notYetInTournament = !tournament.players.includes(player._id)
const searchTermInName = player.name.toLowerCase().includes(searchTerm.toLowerCase())
return notYetInTournament && searchTermInName
})
if (searchTerm) player_id = selectablePlayers[0]?._id ?? ''
} else {
selectablePlayers = players
}
}
function addPlayerToTournament() {
tournament.players = [...tournament.players, player_id];
player_id = "";
console.info(tournament.players);
axios
.put(
"http://localhost:3001/api/tournaments/" + tournament_id,
tournament
)
.then((response) => {
getTournament();
});
}
</script>
<body>
<div>
<h3>Add Players</h3>
<!-- Add an input element for the search bar -->
<div
class = "input-button-container mb-2"
style = "display: flex; align-items: center;"
>
<input
class = "rounded line"
type = "text"
bind:value = {searchTerm}
placeholder = " Search for a player"
/>
<button
class = "btn btn-primary line"
on:click = {addPlayerToTournament} disabled = {player_id === ''}>Update</button
>
</div>
<select class = "form-select" bind:value = {player_id} id = "player">
<option value = "" disabled>please select player</option>
{#each selectablePlayers as player, i}
<option value = {player._id}>{player.name}</option>
{/each}
</select>
</div>
</body>
Можно просто выложить все в один блок клоуда, так как он из одного компонента - меньше работы лучше читать :) Это Репл к ответу svelte.dev/repl/046d38b0384343f5bfc2712281b51c23?version=3.55.0
Внутри
addPlayerToTournamentесть только.push(), возможно здесь не хватает задания -> svelte.dev/…