27
votes

How can I pass a value of a PHP variable to a Vue component in Laravel blade files?

In my example, I have an inline template client-details, I get this view from Laravel so now I want to pass the id which comes with the url /client/1 to my Vue instance.

My component, which is loaded by Laravel, looks like:

<client-details inline-template>
    <div id="client-details" class="">
          My HTML stuff
    </div>
</client-details>

and mounted by:

Vue.component('client-details', {
    data(){
        return {
            clientId: null
        }
    },
);

I already tried like

:clientId="{{ $client->id }"

but it does not work.

4

4 Answers

35
votes

You have to use Vue's props to be able to pass attributes to Vue's components through markup. Take a look at the following example:

<client-details inline-template client-id="{{ $client->id }}">
    <div id="client-details" class="">
          My HTML stuff
    </div>
</client-details>

In your Vue component:

Vue.component('client-details', {
    props: [
        {
            name: 'clientId',
            default:0,
        }
    ]
});

Now in other parts of your Vue component, you can access this value as this.clientId.

Issue Details

Please note that in HTML we write attribute name in kebab-case but in Vue side we write it in camelCase. More info in official docs here.

Also, you are using Vue's v-bind shorthand in :clientId="{{ $client->id }}" which means that Vue will deal anything inside double quotes as a JavaScript expression, therefore you may get errors in that case as well. Instead, you should use this format clientId="{{ $client->id }} without a colon.

12
votes

I just did this and it's working great for me. Using Laravel 5.4 and Vue 2.x.

In my component, declare a property (props) for the object:

props: ['currentUser'],

On my blade page where the component is instantiated:

<my-component v-bind:current-user='{!! Auth::user()->toJson() !!}'></my-component>

Note that in the component, I am using camelCase for currentUser, but because html is case-insensitive, you have to use kebab-case (thus, the 'current-user').

Also note, if you use blade syntax {{ }} then the data between is run through php htmlspecialchars. if you want unencoded data (which in this case you would), then use {!! !!}

6
votes

For anyone who comes across this thread and is still getting errors, the answer is correctly given above by Mustafa Ehsan, but not explained. Trial and error helped me see it.

My component in newuser.blade.php

<access-request
       firstname="{{ $newuser->firstname }}"
       lastname="{{ $newuser->lastname }}"
       accessid="{{ $newuser->id }}"
>
</access-request>

Its very important to note the binding method used. On the component above, I wrote only the name of the data binding (like React props), then registered it on the component props (see below). This is how Mustafa wrote his binding in his answer, and works fine. The other, more Vue way to pass the props is with the v-bind: or :, but you have to make sure to use both double-quotes and single-quotes:

:firstname="'{{ $newuser->firstname }}'"

Without both quotes, you get Vue warnings.

AccessRequest.vue:

<template>
   <div class="component">
        <h3 class="">{{ firstname }} {{ lastname }}</h3>
        <p>Access ID: {{ accessid }}</p>
        <label for="administrator">Grant Administrator Priviledges:</label>
        <input name="administrator" type="checkbox" value="True" class="mb-5"><br>
        <button type="submit" class="btn btn-success">Add</button>
        <button type="submit" class="btn btn-danger">Delete</button>
        <hr>
   </div>
</template>

<script>
  export default {
    name: "AccessRequest",
    props: ['firstname', 'lastname', 'accessid'],
  }
</script>
2
votes

I had to pass some server data to my Vue component, I ended up creating a $server_data variable in the controller and passing it in a json script tag.

In the controller:

$server_data = json_encode([
    "some-data" => SomeObject::all()
]);

return View::make('myview', compact('server_data'));

In the template:

<script type="application/json" name="server-data">
    {{ $server_data }}
</script>
<!-- Inserts server data into window.server_data -->
<script>
    var json = document.getElementsByName("server-data")[0].innerHTML;
    var server_data = JSON.parse(json);
</script>

In the vue initialisation, I put a computed property:

computed: {
    'server_data': function(){
        return window.server_data;
    }
}

Then, the data is accessible in the component template with server_data.some_object.

This allows to pass a lot of structured data without needing many html attributes. Another benefit is that the data is escaped by the the json encoding. This avoids potential bugs with variables that contain double quotes ("), which would mess up the dom.