Search code examples
javascriptvue.jsvue-resource

Passing data from parent component to a child component


I have a parent component as follows

<template>
        <div class="row">
            <mappings mapping-list="{{currentMappings}}"></mappings>
        </div>
</template>

<script>
    import Mappings from './content/Mappings.vue';

    export default {
      data () {
       return {
         currentMappings: Array
       }
      },
      created () {
        this.readData();
      },
      methods: {
        readData () {
            this.$http.get('data/Books.xml').then((response)=> {
                var x2js = new X2JS();
                var jsonObj = x2js.xml_str2json( response.body );
                this.getMappings(jsonObj.WAStatus);
            });
        }, 
        getMappings (jsonObj) {
            this.currentMappings = jsonObj.WSSMappings;
        }
      },
      components: { Mappings }
    };
</script>

and a child "mappings" component as follows

<template>
        <div class="col-lg-4">
            <div class="hpanel stats">
                <div class="panel-body h-200">
                    <div class="stats-title pull-left">
                        <h3>Mappings</h3>
                    </div>
                    <div class="stats-icon pull-right">
                        <img src="images/mappings.png" class="browserLogo">

                    </div>
                    <div class="m-t-xl">
                        <table class="table table-striped table-hover">
                                <tr v-for="mapping in mappingList ">
                                    <td>name - {{$index}}</td>
                                </tr>
                        </table>
                    </div>
                </div>
                <div class="panel-footer">
                    Current WSS - SA Mappings
                </div>
            </div>
        </div>
</template>
<script>
    export default {
        props: {
            mappingList:Array
        },
        created () {
            console.log(this.mappingList);
            // console.log(this.$parent.mappings);
        }
    }
</script>

I am unable to pass data from the parent component to the child component. I am trying to use props here. The error that I am getting is

main.js:2756[Vue warn]: Invalid prop: type check failed for prop "mappingList". Expected Array, got String. (found in component: <mappings>)

Update As per the suggestions made I have updated the parent component as follows

<template>
        <div class="row">
            <browser-stats></browser-stats>
        </div>
        <div class="row">
            <mappings :mapping-list="currentMappings"></mappings>
        </div>
</template>

<script>

    import Mappings from './content/Mappings.vue';

    export default {
      data () {
       return {
         currentMappings: []
       }
      },
      created () {
        this.readData();
      },
      methods: {
        readData () {
            this.$http.get('data/WA_Status.xml').then((response)=> {
                var x2js = new X2JS();
                var jsonObj = x2js.xml_str2json( response.body );
                this.getMappings(jsonObj.WAStatus);
            });
        }, 
        getMappings (jsonObj) {
            this.currentMappings = jsonObj.WSSMappings;
         console.log(this.currentMappings.length);
        console.log(JSON.stringify(this.currentMappings));
        }
      },
      components: {  Mappings }
    };
</script>

and the child "mappings" component as follows

<template>
        <div class="col-lg-4">
            <div class="hpanel stats">
                <div class="panel-body h-200">
                    <div class="stats-title pull-left">
                        <h3>Mappings</h3>
                    </div>
                    <div class="stats-icon pull-right">
                        <img src="images/mappings.png" class="browserLogo">

                    </div>
                    <div class="m-t-xl">
                        <table class="table table-striped table-hover">
                                <tr v-for="mapping in mappingList ">
                                    <td>{{mapping._name}}</td>
                                </tr>
                        </table>
                    </div>
                </div>
                <div class="panel-footer">
                    Current WSS - SA Mappings
                </div>
            </div>
        </div>
</template>
<script>
    export default {
        props: {
            mappingList:[]
        }
    }
</script>

but I am getting an empty mappingList which means whenever I am doing console.log(this.currentMappings.length); I get undefined.. Can you please let me know what I am doing wrong here ?

Thanks


Solution

  • 1) Fist issue

      data () {
       return {
         currentMappings: Array
       }
    

    Should be

      data () {
       return {
         currentMappings: []
       }
    

    2) Second issue

    <mappings mapping-list="{{currentMappings}}"></mappings>
    

    Should be:

    <mappings :mapping-list="currentMappings"></mappings>
    

    3) Third issue

        created () {
            console.log(this.mappingList);
            // console.log(this.$parent.mappings);
        }
    

    This will return empty array every time. Because mappingList changed via AJAX and it's happed after created() was called. Try to use vue-devtool (chrome plugin) for better debug experience.

    UPDATED: To be able to watch async changes (like made with AJAX) consider to use watch this way:

    {
       data(){ 
          //..
       },
       watch:{
          'currentMappings'(val){
              console.log('currentMappings updated', currentMappings);
          }
       }
    }
    

    Docs are here.