1

I have a display component (app-display) with dynamic component inside (by default: app-empty):

    app.component('appDisplay', {
        template: `<component :is="currentComponent"></component>`,
        data() {
            return {currentComponent: 'appEmpty'}
        }
    });

I need to create new instance of app-message, to set property message for this instance and to set the instance as current component for app-display on button click.

This is a browser code for the question:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue component reference</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app"></div>
<script>
    // main application with button & display panel
    const app = self.Vue.createApp({
        template: `
          <app-btn></app-btn>
          <app-display></app-display>
        `
    });

    // button component to fire action
    app.component('appBtn', {
        template: `
          <button v-on:click="setDisplay">Display message</button>`,
        methods: {
            setDisplay() {
                console.log('I need to set "appMessage" (with some "message" param) as inner component to "app-display" here.');
            }
        }
    });

    // component with dynamic component inside
    app.component('appDisplay', {
        template: `<component :is="currentComponent"></component>`,
        data() {
            return {currentComponent: 'appEmpty'}
        }
    });

    // default component to display
    app.component('appEmpty', {
        template: `<div>I'm empty.</div>`
    });

    // this component with custom message should be displayed on button click
    app.component('appMessage', {
        template: `
          <div>{{ message }}</div>
        `,
        props: {
            message: String
        }
    });
    // mount main app to the page
    app.mount('#app');
</script>
</body>
</html>

How can I access app-display from app-btn?

2
  • 1
    did you try out event bus? please check this answer Commented Nov 23, 2020 at 17:33
  • 2
    An event bus can be good for small apps, but there are several known pitfalls so avoid using it for larger apps. A state management solution is generally better Commented Nov 23, 2020 at 21:32

1 Answer 1

1

You should emit an event from button component to main component with component name to display and the message and in the main component you should define a message and current component name which will be updated by the handler of the emitted event and passed as props to the component that displays them:

   // main application with button & display panel
    const app = self.Vue.createApp({
        template: `
          <app-btn @change-content="changeContent"></app-btn>
          <app-display :currentComponent="componentName" :message="msg"></app-display>
        `,
        data(){
         return{
            componentName:'appEmpty',
            msg:''
         }
        },
        methods:{
           changeContent(compName,msg){
           console.log(compName,msg)
             this.componentName=compName
             this.msg=msg
           }
        }
    });

    // button component to fire action
    app.component('appBtn', {
        template: `
          <button v-on:click="setDisplay">Display message</button>`,
        methods: {
            setDisplay() {
            this.$emit('change-content','appMessage','Hello message :)')
            
            }
        }
    });

    // component with dynamic component inside
    app.component('appDisplay', {
        props:{
        currentComponent:{
             type:String,
             default:'appEmpty'
           }
        },
        template: `<component :is="currentComponent"></component>`,
      
    });

    // default component to display
    app.component('appEmpty', {
        template: `<div>I'm empty.</div>`
    });

    // this component with custom message should be displayed on button click
    app.component('appMessage', {
        template: `
          <div>{{ message }}</div>
        `,
        props: {
            message: String
        }
    });
    // mount main app to the page
    app.mount('#app');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue component reference</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app"></div>

</body>
</html>

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

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.