Laravel Nova - раскрывающееся поле загрузки, основанное на связи с другим раскрывающимся списком

У меня есть этот ресурс под названием Distributor

  ID::make()->sortable(),
            Text::make('Name')
                ->creationRules('required'),
            BelongsTo::make('Region')
                ->creationRules('required')
                ->searchable(),
            BelongsTo::make('Country')
                ->creationRules('required')
                ->searchable(),

До сих пор все на месте. Но модель Country должна зависеть от Regionmodel, поэтому, когда я выбираю регион, я хочу отображать параметры со странами, относящимися к этому региону.

Регион и Страна уже связаны в своих моделях на основе belongsToMany отношений.

Есть ли способ совместить эти поля?


person Tudor-Radu Barbu    schedule 29.01.2019    source источник


Ответы (2)


Ответ Эрика мне очень помог. Спасибо!

Но вместо того, чтобы писать собственные функции заполнения и разрешения в настраиваемом поле Nova, я просто унаследовал поле BelongsTo:

<?php

namespace Travelguide\DestinationSelect;

use App\Models\Destination;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Http\Requests\NovaRequest;

class DestinationSelect extends \Laravel\Nova\Fields\BelongsTo
{
  /**
   * The field's component.
   *
   * @var string
   */
  public $component = 'destination-select';

  /**
   * Prepare the field for JSON serialization.
   *
   * @return array
   */
  public function jsonSerialize()
  {
    $parentId = null;
    $parentName = null;

    if (isset($this->belongsToId)) {
      $destination = Destination::where('id', $this->belongsToId)->first();
      if (isset($destination) && isset($destination->parent)) {
        $parentId = $destination->parent->id;
        $parentName = $destination->parent->name;
      }
    }

    return array_merge([
      'parent_id' => $parentId,
      'parent_name' => $parentName,
    ], parent::jsonSerialize());
  }
}

Затем можно использовать дополнительные данные в функции jsonSerialize для предварительного заполнения элемента выбора внешнего интерфейса:

<template>
  <default-field :field="field" :errors="errors">
    <template slot="field">
      <select
        name="country"
        ref="menu"
        id="country"
        class="form-control form-select mb-3 w-full"
        v-model="selectedCountryId"
        @change="onCountryChange"
      >
        <option
          :key="country.id"
          :value="country.id"
          v-for="country in countries"
        >
          {{ country.name }}
        </option>
      </select>

      <select
        v-if="regions.length > 0"
        name="region"
        ref="menu"
        id="region"
        class="form-control form-select mb-3 w-full"
        v-model="selectedRegionId"
      >
        <option :value="region.id" :key="region" v-for="region in regions">
          {{ region.name }}
        </option>
      </select>
    </template>
  </default-field>
</template>

<script>
import { FormField, HandlesValidationErrors } from "laravel-nova";

export default {
  mixins: [FormField, HandlesValidationErrors],

  props: ['resourceName', 'field'],

  data() {
    return {
      countries: [],
      regions: [],
      selectedCountryId: null,
      selectedRegionId: null
    };
  },

  created: function() {
    this.fetchCountries();
  },

  methods: {

    async fetchCountries() {
      const countryResponse = await Nova.request().get("/api/destinations");
      this.countries = countryResponse.data;

      // Add 'null' option to countries
      this.countries.unshift({
        name: '-',
        id: null
      });

      if (this.field.parent_id) {
        this.selectedCountryId = this.field.parent_id;
        this.selectedRegionId = this.field.belongsToId || null;
      } else {
        this.selectedCountryId = this.field.belongsToId || null;
      }

      this.updateRegionDropdown();
    },

    async updateRegionDropdown() {
      if (!this.selectedCountryId) {
        return;
      }

      // Get all regions of the selected country
      const regionResponse = await Nova.request().get("/api/destinations/" + this.selectedCountryId);
      this.regions = regionResponse.data;

      // Add 'null' option to regions
      this.regions.unshift({
        name: '-',
        id: null
      });
    },

    onCountryChange() {
      // De-select current region and load all regions of new country
      this.selectedRegionId = null;
      this.updateRegionDropdown();
    },

    fill(formData) {
      if (this.selectedRegionId) {
        formData.append('destination', this.selectedRegionId);
      } else if (this.selectedCountryId) {
        formData.append('destination', this.selectedCountryId);
      }
    },
  },
};
</script>
person Birdperson    schedule 04.02.2020

Для этого есть пакет laravel nova:

https://novapackages.com/packages/orlyapps/nova-belongsto-depend

Может быть, самый простой способ сделать это!

person Juliatzin    schedule 21.08.2020