简体   繁体   中英

How do I pass a blade variable to a vue instance so I can use it in my JavaScript file?

I am building an access control list where every role in the application will have a set of permissions. I am trying to create an Edit Role page which would show a list of check boxes and the selected boxes would be the permissions that role already has. I have an array of permissions associated to a role that I want to have access to from my JavaScript file. That is, I have an array $role->permissions->pluck('name')) that I want to have access to from my Vue instance. Then from this instance, bind the property permissionsSelected to the checkboxes in my blade file. This is my edit page. (I am using the UI component Buefy for the checkboxes hence the tag <b-checkbox></b-checkbox> )

Edit.blade.php

@extends('layouts.manage')

@section('content')
<div class="flex-container">
<div class="columns m-t-10">
  <div class="column">
    <h1 class="title">Edit {{$role->display_name}}</h1>
  </div>
  <div class="column">
    <a href="{{route('roles.edit', $role->id)}}" class="button is-primary is-pulled-right"><i class="fa fa-user-plus m-r-10"></i> Edit this Role</a>
  </div>
</div>
<hr class="m-t-0">
<form action="{{route('roles.edit', $role->id)}}" method="POST">
  {{ csrf_field() }}
  {{ method_field('PUT') }}

<div class="columns">
  <div class="column">
    <div class="box">
      <article class="media">
        <div class="media-content">
          <div class="content">
            <h2 class="title">Role Details:</h2>

            <div class="field">
              <p class="control">
                <label for="display_name" class="label">Name (Human Readable)</label>
                <input type="text" class="input" name="display_name" value="{{$role->display_name}}" id="display_name">
              </p>

            </div>

            <div class="field">
              <p class="control">
                <label for="name" class="label">Slug (Cannot be edited)</label>
                <input type="text" class="input" name="name" value="{{$role->name}}" disabled id="name">
              </p>

            </div>

            <div class="field">
              <p class="control">
                <label for="description" class="label">Description</label>
                <input type="text" class="input" value="{{$role->description}}" id="description">
              </p>

            </div>

          </div>
        </div>
      </article>
    </div>
  </div>
</div>

<div class="columns">
  <div class="column">
    <div class="box">
      <article class="media">
        <div class="media-content">
          <div class="content">
            <h2 class="title">Permissions:</h2>

              @foreach ($permissions as $permission)
                <div class="field">
                  <b-checkbox v-model="permissionsSelected" native-value="{{$permission->name}}">{{$permission->display_name}} <em>({{$permission->description}})</em></b-checkbox>
                </div>

              @endforeach


          </div>
        </div>
      </article>
    </div>
  </div>
</div>
</form>
</div>
@endsection

This is the Vue instance in my JavaScript file App.js

const app = new Vue({
el: '#app',
data: {
    auto_password: true,
    password_options: 'keep',
    permissionType: 'basic',
    permissionsSelected: '',
resource: '',
crudSelected: ['create', 'read', 'update', 'delete']
    },

    methods: {
    crudName: function(item) {
      return item.substr(0,1).toUpperCase() + item.substr(1) + " " + app.resource.substr(0,1).toUpperCase() + app.resource.substr(1);
    },
    crudSlug: function(item) {
      return item.toLowerCase() + "-" + app.resource.toLowerCase();
    },
    crudDescription: function(item) {
      return "Allow a User to " + item.toUpperCase() + " a " + app.resource.substr(0,1).toUpperCase() + app.resource.substr(1);
    }
  }
 });

I want to be able to do something like this permissionsSelected: {!!$role->permissions->pluck('id')!!} in my JS file. How do I solve this?

There are two ways to get the data from Php to Vue.

  1. To use network calls. Expose a rest endpoint, hit it and get the data. This is the ideal case but involves a lot of extra work

  2. Pass the data using data attributes , I think in your case you will want to use this. So how can we do this?

First we should add an id to an HTML element. Then add a data attribute to it. Then use blade templating to parse your data as json and set the data attribute to this. Then in the created/mounted hook in vue extract the data and set to the state.

<div id="custom-data" data-profiles="{{someVar.json}}">
  Any content as ususal
</div>

PS I'm not aware of blade and PHP syntax so someVar.json may not be correct.

In the vue mounted hook, I will do something like this.

created() {
  const el = document.getElementById('custom-data')
  const profiles = JSON.parse(el.dataset.profiles)
  this.profiles = profiles
}

Just FYI, the second method is very popular and even Laracast use this technique. :) Here is the link to the podcast .

I also think the laracast vue tutorial talks about using this method.

I hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM