Laravel - ввод формы - множественный выбор для отношения одного к другому

Одно из требований в приложении, которое я создаю, - это ввод формы, который принимает различное количество элементов для одного поля. Например, спорт, в котором я играю ( "Футбол", "Теннис", "Крокет" ).

Есть конечное количество спортивных игр, которые можно играть (возможно), поэтому эти элементы должны быть выбраны из списка типов "drop down" в форме ввода.

Внизу этой формы будут две таблицы, которые имеют отношения "один ко многим". Таким образом, из вышеизложенного таблица "user" будет иметь одну строку, а таблица "user_sports" - три строки. Затем они будут связаны полем id в таблице пользователя.


Я не смог найти такую ​​функциональность, где это может быть достигнуто в документации (возможно, я не искал правильную вещь). Ниже было самое близкое, что я нашел, но только для выбора одного элемента из выпадающего списка.

http://laravel.com/docs/html#drop-down-lists


Есть ли обходной путь, который позволит мне получить этот элемент формы и запустить с помощью рамки Laravel?

В качестве альтернативы существуют ли другие способы обеспечения такого рода функциональности без ущерба для пользователя?

Ответы

Ответ 1

Я согласен с user3158900, и я немного отличаюсь только тем, как я его использую:

{{Form::label('sports', 'Sports')}}
{{Form::select('sports',$aSports,null,array('multiple'=>'multiple','name'=>'sports[]'))}}

Однако, по моему опыту, третий параметр select - это только строка, поэтому для повторной обработки данных для множественного выбора мне пришлось сделать что-то вроде этого:

<select multiple="multiple" name="sports[]" id="sports">
@foreach($aSports as $aKey => $aSport)
    @foreach($aItem->sports as $aItemKey => $aItemSport)
        <option value="{{$aKey}}" @if($aKey == $aItemKey)selected="selected"@endif>{{$aSport}}</option>
    @endforeach
@endforeach
</select>

Ответ 2

@SamMonk ваша техника велика. Но вы можете использовать помощник формы laravel для этого. У меня есть отношения с клиентом и собакой.

На вашем контроллере

$dogs = Dog::lists('name', 'id');

В окне создания клиента вы можете использовать.

{{ Form::label('dogs', 'Dogs') }}
{{ Form::select('dogs[]', $dogs, null, ['id' => 'dogs', 'multiple' => 'multiple']) }}

Третий параметр принимает список массива a well. Если вы определяете отношения на своей модели, вы можете сделать это:

{{ Form::label('dogs', 'Dogs') }}
{{ Form::select('dogs[]', $dogs, $customer->dogs->lists('id'), ['id' => 'dogs', 'multiple' => 'multiple']) }}

Обновление для Laravel 5.1

Теперь метод списков возвращает коллекцию. Обновление до 5.1.0

{!! Form::label('dogs', 'Dogs') !!}
{!! Form::select('dogs[]', $dogs, $customer->dogs->lists('id')->all(), ['id' => 'dogs', 'multiple' => 'multiple']) !!}

Ответ 3

Laravel 4.2

@ SamMonk дал лучшую альтернативу, я последовал его примеру и построил последний фрагмент кода

<select class="chosen-select" multiple="multiple" name="places[]" id="places">
    @foreach($places as $place)
        <option value="{{$place->id}}" @foreach($job->places as $p) @if($place->id == $p->id)selected="selected"@endif @endforeach>{{$place->name}}</option>
    @endforeach
</select>

В моем проекте у меня будет много табличных отношений, поэтому я написал расширение, чтобы сохранить его в чистоте. Чтобы загрузить его, поместите его в некоторый файл конфигурации, например, "app/start/global.php". Я создал файл "macros.php" в каталоге "app/" и включил его в EOF global.php

// app/start/global.php
require app_path().'/macros.php';

// macros.php
Form::macro("chosen", function($name, $defaults = array(), $selected = array(), $options = array()){

    // For empty Input::old($name) session, $selected is an empty string
    if(!$selected) $selected = array();

    $opts = array(
        'class' => 'chosen-select',
        'id' => $name,
        'name' => $name . '[]',
        'multiple' => true
    );
    $options = array_merge($opts, $options);
    $attributes = HTML::attributes($options);

    // need an empty array to send if all values are unselected
    $ret = '<input type="hidden" name="' . HTML::entities($name) . '[]">';
    $ret .= '<select ' . $attributes . '>';
    foreach($defaults as $def) {
        $ret .= '<option value="' . $def->id . '"';
        foreach($selected as $p) {
            // session array or passed stdClass obj
            $current = @$p->id ? $p->id: $p;
            if($def->id == $current) {
                $ret .= ' selected="selected"';
            }
        }
        $ret .= '>' . HTML::entities($def->name) . '</option>';
    }
    $ret .= '</select>';
    return $ret;
});

Использование

Список без предварительно выбранных элементов (создать представление)

{{ Form::chosen('places', $places, Input::old('places')) }}

Предварительный просмотр (просмотр)

{{ Form::chosen('places', $places, $job->places) }}

Полное использование

{{ Form::chosen('places', $places, $job->places, ['multiple': false, 'title': 'I\'m a selectbox', 'class': 'bootstrap_is_mainstream']) }}

Ответ 4

Множественный выбор - это просто выбор с атрибутом multiple. Имея это в виду, это должно быть так же просто, как...

Form::select('sports[]', $sports, null, array('multiple'))

Первый параметр - это просто имя, но пост-исправление его с помощью [] будет возвращать его в виде массива при использовании Input::get('sports').

Второй параметр - это массив выбираемых параметров.

Третий параметр - это массив параметров, которые вы хотите предварительно выбрать.

Четвертый параметр фактически устанавливает это как раскрывающееся меню с множественным выбором, добавляя свойство multiple к фактическому элементу выбора.

Ответ 5

Мое решение, это сделать с выбранным jquery и bootstrap, id для jquery, выбранным, проверенным и работающим, у меня были проблемы с конкатенацией @foreach, но теперь мы работаем с двойным @foreach и double @if:

  <div class="form-group">
    <label for="tagLabel">Tags: </label>
    <select multiple class="chosen-tag" id="tagLabel" name="tag_id[]" required>
      @foreach($tags as $id => $name)
        @if (is_array(Request::old('tag_id')))
                <option value="{{ $id }}" 
                @foreach (Request::old('tag_id') as $idold)
                  @if($idold==$id)
                    selected
                  @endif 
                @endforeach
                style="padding:5px;">{{ $name }}</option>
        @else
          <option value="{{ $id }}" style="padding:5px;">{{ $name }}</option>
        @endif
      @endforeach
    </select>
  </div>

это выбранный код por jquery (код blade.php не нужен, чтобы этот код работал)

    $(".chosen-tag").chosen({
  placeholder_text_multiple: "Selecciona alguna etiqueta",
  no_results_text: "No hay resultados para la busqueda",
  search_contains: true,
  width: '500px'
});

Ответ 6

Это может быть лучше, чем верхний ответ, если вам нужно сравнить 2 выходных массива друг с другом, но использовать первый массив для заполнения параметров.

Это также полезно, когда в вашем массиве есть нечисловой или смещенный индекс (ключ).

<select name="roles[]" multiple>
    @foreach($roles as $key => $value)
        <option value="{{$key}}" @if(in_array($value, $compare_roles))selected="selected"@endif>
            {{$value}}
        </option>
    @endforeach
</select>