Skip to content
Advertisement

Render component template on invoked methods

So while I’m learning vue, I wanted to double check if someone can show me what I’m doing wrong or lead me in the right answer. Below, I will show the code and then explain what I’m attempting to do.

Here is my Vue.js app:

Vue.component('o365_apps_notifications', {
    template:
    `
    <div class="notification is-success is-light">
        // Call the name here and if added/removed.
    </div>
   `,

});

new Vue({
    name: 'o365-edit-modal',
    el: '#o365-modal-edit',
    components: 'o365_apps_notifications',
    data() {
        return {
            list: {},
            movable: true,
            editable: true,
            isDragging: false,
            delayedDragging: false,
            options: {
                group: 'o365apps',
                disabled: true,
                handle: '.o365_app_handle',
            }
        }
    },
    methods: {
        add(index, obj) {
            console.log(obj.name);
            this.$data.list.selected.push(...this.$data.list.available.splice(index, 1));
            this.changed();
        },
        remove(index, obj) {
            console.log(obj.name);
            this.$data.list.available.push(...this.$data.list.selected.splice(index, 1));
            this.changed();
        },
        checkMove(evt) {
            console.log(evt.draggedContext.element.name);
        },
    },
});

Here is my modal:

<div id="o365-modal-edit" class="modal">
    <div class="modal-background"></div>
    <div class="modal-card px-4">
        <header class="modal-card-head">
            <p class="modal-card-title">Applications</p>
            <button class="delete" aria-label="close"></button>
        </header>
        <section class="modal-card-body">
            <div class="container">
                <div id="o365-modal-edit-wrapper">
                    <div class="columns">
                        <div class="column is-half-desktop is-full-mobile buttons">
                            // Empty
                        </div>
                        <div class="column is-half-desktop is-full-mobile buttons">
                            // Empty
                        </div>
                    </div>
                </div>
            </div>
        </section>
        <footer class="modal-card-foot">
            <o365-apps-notifications></o365-apps-notifications>
        </footer>
    </div>
</div>

Here is what I’m attempting to do:

Inside my modal, I have my o365_apps_notifications html tag called, my add() and remove() methods output a name on each add/remove using console.log(obj.name); and my checkMove method also drags the same name on drag as shown below:

  1. How could I get my component to render and output the name inside the modal footer? I’ve tried all methods, but I can’t seem to figure out how to trigger the component.

  2. Also, would I have to do something special to make the component fade out after a set timeframe?

All help is appreciated!

Advertisement

Answer

A couple issues:

  1. You’ve declared the notification component with underscores (o365_apps_notifications), but used hyphens in the modal’s template. They should be consistent (the convention is hyphens).

  2. The notification component is declared globally (with Vue.component), but it looks like you’re trying to add it to the modal’s components, which is intended for local components. Only one registration is needed (the global component registration should do).

<o365-apps-notifications>

The notification component should have public props that take the item name and state:

Vue.component('o365-apps-notifications', {
  props: {
    item: String,
    isAdded: Boolean
  },
})

Then, its template could use data binding to display these props.

Vue.component('o365-apps-notifications', {
  template:
   `<div>
      {{ item }} {{ isAdded ? 'added' : 'removed '}}
    </div>`
})

For the fade transition, we want to conditionally render this data based on a local Boolean data property (e.g., named show):

Vue.component('o365-apps-notifications', {
  template:
   `<div v-if="show">
      ...
    </div>`,
  data() {
    return {
      show: false
    }
  }
})

…and add the <transition> element along with CSS to style the fade:

Vue.component('o365-apps-notifications', {
  template:
   `<transition name="fade">
      <div v-if="show">
        ...
      </div>
    </transition>`,
})
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}

To automatically fade out the data, add a watch on item, which sets show=true and then show=false after a delay:

Vue.component('o365-apps-notifications', {
  watch: {
    item(item) {
      if (!item) {
        return;
      }
      this.show = true;

      clearTimeout(this._timer);
      this._timer = setTimeout(() => this.show = false, 1000);
    }
  }
})

Usage

In the modal component, declare local data properties that hold the currently added/removed item:

new Vue({
  el: '#o365-modal-edit',
  data() {
    return {
      changedItem: null,
      changedItemIsAdded: false,
    }
  },
})

Also update add() and remove() to set these properties:

new Vue({
  methods: {
    add(index, obj) {
      this.changedItem = obj.name;
      this.changedItemIsAdded = true;
    },
    remove(index, obj) {
      this.changedItem = obj.name;
      this.changedItemIsAdded = false;
    },
  },
})

Then in the modal component’s template, bind these properties to the notification component’s props:

<o365-apps-notifications :item="changedItem" :is-added="changedItemIsAdded"></o365-apps-notifications>

demo

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement