Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass prop as module name when mapping to namespaced module

I'm trying to pass the store module namespace via props to a component. When I try and map to getters with the prop, it throws this error,

Uncaught TypeError: Cannot convert undefined or null to object

If I pass the name as a string it works.

This Works

<script>
export default {

  props: ['store'],

  computed: {
    ...mapGetters('someString', [
      'filters'
    ])
  }
}
</script>

This does not work

this.store is defined
this.store typeof is a String

<script>
  export default {

    props: ['store'],

    computed: {
      ...mapGetters(this.store, [
        'filters'
      ])
    }
  }
</script>
like image 631
MrGood Avatar asked Mar 03 '17 17:03

MrGood


1 Answers

I used this style utilising beforeCreate to access the variables you want, I used the props passed into the component instance:

import { createNamespacedHelpers } from "vuex";
import module from '@/store/modules/mymod';

export default {
  name: "someComponent",
  props: ['namespace'],
  beforeCreate() { 
    let namespace = this.$options.propsData.namespace;
    const { mapActions, mapState } = createNamespacedHelpers(namespace);

    // register your module first
    this.$store.registerModule(namespace, module);

    // now that createNamespacedHelpers can use props we can now use neater mapping
    this.$options.computed = {
      ...mapState({
        name: state => state.name,
        description: state => state.description
      }),

      // because we use spread operator above we can still add component specifics
      aFunctionComputed(){ return this.name + "functions";},
      anArrowComputed: () => `${this.name}arrows`,
    };

    // set up your method bindings via the $options variable
    this.$options.methods = {
      ...mapActions(["initialiseModuleData"])
    };
  },

  created() {
    // call your actions passing your payloads in the first param if you need
    this.initialiseModuleData({ id: 123, name: "Tom" });
  }
}

I personally use a helper function in the module I'm importing to get a namespace, so if I hadmy module storing projects and passed a projectId of 123 to my component/page using router and/or props it would look like this:

import { createNamespacedHelpers } from "vuex";
import projectModule from '@/store/project.module';

export default{
  props['projectId'], // eg. 123
  ...
  beforeCreate() {

    // dynamic namespace built using whatever module you want:
   let namespace = projectModule.buildNamespace(this.$options.propsData.projectId); // 'project:123'

   // ... everything else as above with no need to drop namespaces everywhere
   this.$options.computed = {
      ...mapState({
        name: state => state.name,
        description: state => state.description
      })
   }
  }
}

Hope you find this useful.

like image 134
Tom 'Blue' Piddock Avatar answered Oct 16 '22 11:10

Tom 'Blue' Piddock