1

I have a form component where I use a child component. I want to use data from the child component within the parent.

My component in html:

<candidates-form endpoint='/candidates/create' buttontext='Add Candidate'></candidates-form>

Then here is the Vue instance:

CandidatesForm.vue

<template>
<div class='row'>

    <div class='form-group'>
        <label>Name:</label>
        <input type='text' class='form-control' v-model='name'>
    </div>
    <div class='form-group'>
        <location-input></location-input>
    </div>

    <button class='btn btn-primary'>{{buttontext}}</button>
</div>
</template>
<script>
    export default {
        data() {
            return {}
        },

        props: ['endpoint', 'buttontext'],

        ready() {}
    }
</script>

I utilize the locationInput component in there and it renders to the screen nicely. That component implements Google Maps typeahead functionality for the input field and looks like this:

LocationInput.vue

<template>

    <place-input
            :place.sync="placeInput.place"
            :types.sync="placeInput.types"
            :component-restrictions.sync="placeInput.restrictions"
            class='form-control'
            label='Location: '
            name='location'
    ></place-input>

    <pre>{{ placeInput.place | json }}</pre>

</template>

<script>
    import { PlaceInput, Map } from 'vue-google-maps'

    export default {

        data() {
            return {
                placeInput: {
                    place: {
                        name: ''
                    },
                    types: [],
                    restrictions: {'country': 'usa'}
                }
            }
        },
        props: ['location'],

        components: {
            PlaceInput
        },
        ready() {
        }
    }
</script>
<style>
    label { display: block; }
</style>

I want to submit the name value and information from placeInput.place to the server.

I register both components in my main app file like so:

Vue.component('locationInput', require('./components/LocationInput.vue'));
Vue.component('candidatesForm', require('./components/CandidatesForm.vue'));

const app = new Vue({
    el: 'body'
});

How do I pass the placeInput.place data from location-input component to candidates-form component?

I want to send the placeInput.place and name data from the candidates-form component to the server, most likely using vue-resource.

3 Answers 3

1

Hey no need for a store or Vuex. Pass data using props!

Final solution:

Blade template:

@extends('layouts.app')

@section('content')
    <div class='col-md-6 col-md-offset-3'>
        <h1>Add New Candidate</h1>
        <hr>
        <candidates-form endpoint='/candidates/create' buttontext='Add Candidate'></candidates-form>
    </div>
@stop

Parent Vue component:

<template>
<div>
    <div class='form-group'>
        <label>Name:</label>
        <input type='text' class='form-control' v-model='name'>
    </div>

    <div class='form-group'>
        <location-input :location="locationData"></location-input>
    </div>

    <button class='btn btn-primary'>{{buttontext}}</button>

    <pre>{{ locationData | json }}</pre>
</div>
</template>

<script>
export default {
    data() {
        return {
            locationData: {
                place: {
                    name: ''
                },
                types: [],
                restrictions: {'country': 'usa'}
            }
        }
    },
    props: ['endpoint', 'buttontext']
}
</script>

Child Vue component:

<template>
    <place-input
            :place.sync="location.place"
            :types.sync="location.types"
            :component-restrictions.sync="location.restrictions"
            class='form-control'
            label='Location: '
            name='location'
    ></place-input>
</template>

<script>
    import { PlaceInput, Map } from 'vue-google-maps'

    export default {
        props: ['location'],
        components: {
            PlaceInput
        }
    }
</script>
<style>
    label { display: block; }
</style>

Aaaaand the overall app.js file (this is within a Laravel 5.3 app btw)

import { load } from 'vue-google-maps'

load({
  key: '<API_KEY>',
  v: '3.24',             // Google Maps API version
  libraries: 'places',   // for places input
});

Vue.component('locationInput', require('./components/LocationInput.vue'));
Vue.component('candidatesForm', require('./components/CandidatesForm.vue'));
Vue.component('company-list', require('./components/CompanyList.vue'));

const app = new Vue({
    el: 'body'
});

This article from alligator.io also helped simplify things for me also. I was overthinking it!

Shout out to @GuillaumeLeclerc for the vue-google-maps component: https://github.com/GuillaumeLeclerc/vue-google-maps

Sign up to request clarification or add additional context in comments.

1 Comment

I find adding v-model support to the custom component is a much better solution. You will find here a very helpful article: alligator.io/vuejs/add-v-model-support
0

Check out my answer here VueJS access child component's data from parent , pretty same questions.

If you are working with large scale application, the best option is to use Vuex, it would save you from a lot of troubles.

Otherwise if it's not a bug app, then you can go with my approach, or using Event Bus.

Comments

0

I would recommend the data store approach which is in the VueJS documentation here: https://v2.vuejs.org/v2/guide/state-management.html

Essentially you would have a store.js file that exports a data object for your application. This data object is shared with all of your components.

From the page linked above:

const sourceOfTruth = {}
const vmA = new Vue({
  data: sourceOfTruth
})
const vmB = new Vue({
  data: sourceOfTruth
})

and if you need components to have private state along with shared state:

var vmA = new Vue({
  data: {
    privateState: {},
    sharedState: store.state
  }
})
var vmB = new Vue({
  data: {
    privateState: {},
    sharedState: store.state
  }
})

1 Comment

thanks. Looks like I need to implement a store for this to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.