Laravel 使用 QueryBuilder 时如何避免页面重新加载

Posted

技术标签:

【中文标题】Laravel 使用 QueryBuilder 时如何避免页面重新加载【英文标题】:Laravel How to avoid page reloading when using QueryBuilder 【发布时间】:2021-01-20 07:50:18 【问题描述】:

在我的laravel-应用程序中,我使用spatie/laravel-query-builder 按某些类别过滤工作列表。

所以我的代码现在看起来像这样:

我的控制器:

public function index(Request $request) 

    $regions = Region::all();
    $jobtypes = JobType::all();
    $industries = Industry::all();

    $jobs = QueryBuilder::for(Job::class)
        ->allowedFilters([
            AllowedFilter::exact('region', 'region_id'),
            AllowedFilter::exact('jobtype', 'job_type_id'),
            AllowedFilter::exact('industry', 'industry_id')
        ])
        ->get();

    return view('job.index', compact('jobs', 'regions', 'jobtypes', 'industries'));

我的刀片视图:

<form method="GET" id="jobfilter-form" enctype="multipart/form-data" content=" csrf_token() ">
   <div>
    <p>Location</p>
    @foreach ($regions as $region)
    <label for="$region->id">
        <input type="checkbox" class="chk-filter" name="region" value="$region->id" />
        @if (in_array($region->id, explode(',', request()->input('filter.region'))))
        checked
        @endif
        $region->name
    </label>
    @endforeach
  </div>

  <div>
    <p>Job type</p>
    @foreach ($jobtypes as $jobtype)
    <label for="$jobtype->id">
        <input type="checkbox" class="chk-filter" name="jobtype" value="$jobtype->id" />
        @if (in_array($jobtype->id, explode(',', request()->input('filter.jobtype'))))
        checked
        @endif
        $jobtype->name
    </label>
    @endforeach
  </div>

  <div>
    <p>Industry</p>
    @foreach ($industries as $industry)
    <label for="$industry->id">
        <input type="checkbox" class="chk-filter" name="industry" value="$industry->id" />
        @if (in_array($industry->id, explode(',', request()->input('filter.industry'))))
        checked
        @endif
        $industry->name
    </label>
    @endforeach
  </div>

  <div>
    <button type="submit" id="filter">filter</button>
  </div>
</form>

最后是javascript

function getIds(checkboxName) 
  let checkBoxes = document.getElementsByName(checkboxName);
  let ids = Array.prototype.slice
    .call(checkBoxes)
    .filter(ch => ch.checked == true)
    .map(ch => ch.value);
  return ids;


function filterResults() 
  let regionIds = getIds("region");

  let jobtypeIds = getIds("jobtype");

  let industryIds = getIds("industry");

  let href = "filter?";

  if (regionIds.length) 
     href += "filter[region_id]=" + regionIds;
  

  if (jobtypeIds.length) 
     href += "&filter[job_type_id]=" + jobtypeIds;
  

  if (industryIds.length) 
    href += "&filter[industry_id]=" + industryIds;
  

  document.location.href = href;



$("#jobfilter-form #filter").on("click", e => 
  filterResults();
);

这基本上可以正常工作,但此解决方案(当然)每次单击提交按钮时都会重新加载页面,并且还会取消选中所有先前选中的复选框。

所以我的问题是:我可以避免重新加载页面吗?以及如何保留选中的复选框?

另一件事是,我正在考虑使用这样的东西:

$(".chk-filter").on("change", function() 
   if (this.checked) 
     $('#jobfilter-form button[type="submit"]').click();
   
);

并隐藏提交按钮。

谁能帮帮我?

【问题讨论】:

您可以将整个应用程序重建为 AJAX。要保留复选框,只需通过后端写入它们的状态 【参考方案1】:

当您更新 URL 并使其导航时,这可能会重新加载页面。最好添加一个额外的路由,它接受这些参数并返回 JSON。然后,您可以将您的 web 1.0 样式转换为动态表单,该表单使用 XHR 获取,然后相应地操作 DOM。 CSRF 令牌需要与 XHR 一起使用 passed along - 但通常不需要表单,因为 JS 会获取 JSON 并更新 DOM(这将是显示结果的区域)。当从不提交任何表单时,页面不会重新加载,复选框将保持原样。

【讨论】:

以上是关于Laravel 使用 QueryBuilder 时如何避免页面重新加载的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?

Laravel QueryBuilder 中的 Postgres 函数 WITH

Laravel Eloquent 相当于 QueryBuilder 查询

laravel 5.1 中 Eloquent 和 Query Builder 有啥区别?

Laravel:使用 Query Builder 或 Eloquent ORM 时在每次插入/更新时执行一些任务

Laravel QueryBuilder - 相同查询的 `where()` 和 `whereRaw()` 结果不同