4

I have a form that contains some custom components like custom-input, custom-button, etc. in my custom-form component. My custom components (except custom-form) contain a disabled props. I want to set the disabled props to true in all custom components when a submit button is clicked.

I need to do that dynamically and I don't know which custom components are used in a form. I also need to mention that, It is possible that I have more than one form on a page.

How can I handle that?

Here is what I've tried.

--- Main Component ---
<template>
  <div>
    <slot />
  </div>
</template>
<script>
export default {
}
</script>
--- Component1 ---
<template>
  <div>
    <span v-if="!disabled">this is Comp1</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>
--- Component2 ---
<template>
  <div>
    <span v-if="!disabled">this is Comp2</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>
--- My directive ---
import Vue from 'vue'

Vue.directive('disable', {
  bind: (el, binding, vnode) => {
    methods.setChildrent(vnode.context.$children, binding.value)
  }
})

const methods = {
  setChildrent(children, value) {
    children.forEach(element => {      
      this.setChildrent(element.$children, value)
      if(element.$options.propsData)
        if ('disabled' in element.$props)
          element.$props.disabled = value
    })
  }
}

--- Page ---
<template>
  <MainComp v-disable="true">
    <Comp1></Comp1>
    <Comp2></Comp2>
  </MainComp>
</template>

<script>
import Comp1 from './Comp1.vue'
import Comp2 from './Comp2.vue'
import MainComp from './MainComp.vue'
import Directives from '../directives/index.js'
export default {
  name: 'HelloWorld',
  components: {
    Comp1,
    Comp2,
    MainComp,
  },
  directives: {
    Directives
  },
  props: {
    msg: String
  },
  methods: {
  },
  mounted() {   
  }
}
</script>

2 Answers 2

4

Props!

// main component / view

<template>
    <custom-form />
    <custom-form />
</template>

<script>
import CustomForm from './CustomForm'

export default {
    components: { CustomForm },
    data() {
        return {
            disabled: false
        }
    },
    methods: {
        setDisabled() { 
            this.disabled = true
        }
    }
}
</script>

// CustomForm.vue

<template>
    <form @submit.prevent="submit">
        <custom-element :disabled="disabled" />
        <custom-element :disabled="disabled" />
    </form>
</template>

<script>
    import CustomElement from './CustomElement'

    export default {
        data() { 
            return {
                disabled: true
            }
        },
        props: ['disabled'],
        components: { CustomElement },
        methods: {
            submit() {
                this.disabled = true
            }
        }
    }
</script>

// CustomElement.vue

<template>
    <input :disabled="disabled" />
</template>

<script>
    export default {
        props: ['disabled']
    }
</script>
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you for the answer. Is that possible we do not set :disabled in propsData and dynamically change it through a method? As I mentioned in my question we may have multiple forms on a page and with your approach, all the forms will be disabled.
I am looking for a solution to create a generic and dynamic behavior for all the forms without the need to write :disabled="disabled" in all custom elements.
This is the conventional way, if you introduce something unconventional it will be more troublesome to maintain and learn for anyone else seeing your code. Regarding having multiple forms, you would just expose the prop also on the custom-form element. I will update example.
Thank you for the answer. But even in this model if you submit the first form, it will change the second form disabled property. On the other hand, we don't want to define a specific disabled variable for each form in data section.
Ok so just move the props around so the scope of disabled keeps to <custom-form />
|
1

I solved this issue by the below approach. I don't know if there are any cases that may cause a problem or not but I did some tests and it was fine.

//Component1

<template>
  <div>
    <span v-if="!disabled">this is Comp1</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>

//Component2

<template>
  <div>
    <span v-if="!disabled">this is Comp2</span>
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  }
}
</script>

//MainComponent

<template>
  <div>
    <slot />
  </div>
</template>
<script>
export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    disabled(val) {
      this.setChildrenStatus(val)
    }
  },
  methods: {    
    setChildrenStatus(status) {      
      this.$slots.default.forEach(item => {
        if (item.componentOptions && item.componentOptions.propsData) {
          item.componentOptions.propsData['disabled'] = status
        }
      })
    }    
  }
}
</script>

//Mainpage

<template>
  <MainComp :disabled="disabled">
    <Comp1></Comp1>
    <Comp2></Comp2>
    <br>
    <button @click="setDisabled">submit</button>    
  </MainComp>
</template>

<script>
import Comp1 from './Comp1.vue'
import Comp2 from './Comp2.vue'
import MainComp from './MainComp.vue'
export default {
  name: 'HelloWorld',
  components: {
    Comp1,
    Comp2,
    MainComp,
  },
  data() {
    return {
      disabled: false
    }
  },
  props: {
    msg: String
  },
  methods: {
    setDisabled() {
      this.disabled = !this.disabled
    }
  }
}
</script>


Comments

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.