A
A
Aleksei Burov2019-10-18 16:49:57
Vue.js
Aleksei Burov, 2019-10-18 16:49:57

How, when clicking on a button in a block, open a modal window / pop-up sidebar with the data of the block in which the button is located?

I'm learning vuex, I'm making an interface "like an admin panel"
Interface prototype:
5da9c392bd719875750002.jpeg
I use vuex to store data, the code is below
Vuex container code

export default {
  actions: {
    fetchData(ctx) {
      const data = require('../../data')
      localStorage.setItem('blocks', JSON.stringify(data))
      const blocks = JSON.parse(localStorage.getItem('blocks'))

      ctx.commit('updateBlockConfig', blocks)
    },

    toggle(state) {
      return state.isNavOpen = !state.isNavOpen;
    },

    loadConfigToBlock() {

    }

  },
  mutations: {
    updateBlockConfig(state, blocks) {
      return state.block_config = blocks
    },

    setIsNavOpen(state) {
      return state.isNavOpen = true;
    },

    toggleNav(state, i) {
      state.block_config[i]

      return state.isNavOpen = !state.isNavOpen;
    },

    closeSidebarPanel(state) {
      return state.isNavOpen = !state.isNavOpen;
    }
  },
  state: {
    block_config: [],
    isNavOpen: false,
  },
  getters: {
    getBlockConfig(state) {
      return state.block_config
    },

    getBlockModal(state) {
      return state.block_config.settings
    },

    isPanelOpen(state) {
      return state.isNavOpen
    }
  },
}

The code of the element in which the list of blocks is displayed
<template>
  <div id="app">
    <div class="content">
      <div class="blocks">
        <div class="block" v-for="block in getBlockConfig" :key="block.blockID" v-bind:style="{ background: `${block.color}` }">
          <h2 class="block-title">{{block.bName}}</h2>
          <div class="block-text">{{block.bText}}</div>
          <div>{{block.settings}}</div>
          <Trigger></Trigger> <!-- Кнопка вызова модального окна -->
        </div>
      </div>
      <Sidebar>
        <div class="sidebar-panel-settings">
          <div class="setting-block">
             <!-- Тут вывод данных блока, из которого вызвано окно -->
          </div>
        </div>
      </Sidebar>
    </div>
  </div>
</template>

<script>
import {mapGetters, mapActions} from 'vuex'
import Sidebar from './components/Menu/Sidebar.vue'
import Trigger from './components/Menu/Trigger.vue'

export default {
  name: 'app',
  components: {
    Sidebar,
    Trigger
  },
  computed: mapGetters(['getBlockConfig', 'isPanelOpen']),
  methods: mapActions(['fetchData', 'toggle']),
  async mounted() {
    this.fetchData()
  },
}
</script>

And fake data from json
[
  {
  "blockID": 1,
  "bName": "Желтый блок",
  "bText": "Любая компания-производитель связывает с каждой своей новой моделью определенные надежды. Зачастую в связи с этим звучат громкие и красивые заявления - прорыв, революция, законодатель моды на ближайшее десятилетие... Но время тут - единственный по-настоящему объективный эксперт.",
  "color": "#FFFF00",
  "isOpen": false,
  "settings": [
    {
      "ID": 34,
      "Name": "Ширина",
      "stringType": "int",
      "filedType": "input",
      "fieldValue": "600",
      "fieldSize": 4
    },
    {
      "ID": 35,
      "Name": "Высота",
      "stringType": "int",
      "filedType": "input",
      "fieldValue": "500",
      "fieldSize": 4
    }
  ]
  },
  {
    "blockID": 2,
    "bName": "Розовый блок",
    "bText": "Любая компания-производитель связывает с каждой своей новой моделью определенные надежды. Зачастую в связи с этим звучат громкие и красивые заявления - прорыв, революция, законодатель моды на ближайшее десятилетие... Но время тут - единственный по-настоящему объективный эксперт.",
    "isOpen": false,
    "color": "#ffc0cb",
    "settings": [
      {
        "ID": 39,
        "Name": "Скрытое",
        "stringType": "int",
        "filedType": "input",
        "fieldValue": "600",
        "fieldSize": 4
      }
    ]
  }
]

Button code:
<template>
  <button class="button-config" :class="{ 'active' : isPanelOpen }" @click.prevent="toggleNav" >Настройки</button>
</template>

<script>
import {mapMutations, mapGetters} from 'vuex'

export default {
  name: 'Trigger',
  methods: mapMutations(['toggleNav']),
  computed: mapGetters(['fetchData', 'isPanelOpen']),
}
</script>

Sidebar code:
<template>
    <div class="sidebar">
        <div class="sidebar-backdrop" @click="closeSidebarPanel" v-if="isPanelOpen"></div>
        <transition name="slide">
          <div v-if="isPanelOpen"
                class="sidebar-panel">
                <a href="#" class="close-button" @click="closeSidebarPanel"></a>
              <slot></slot>
          </div>
        </transition>
    </div>
</template>
<script>
import {mapMutations, mapGetters} from 'vuex'

export default {
    name: 'Sidebar',
    methods: mapMutations(['closeSidebarPanel']),
    computed: mapGetters(['isBurgerActive', 'isPanelOpen']),
}
</script>

Actually, the question is how to display a popup with the settings of the block (in the json file, the "settings" sub-object) in the format of the form header with the name of the config + input with the initial data and the "save" button
Tell me how best to implement this.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2019-10-18
@aleksspectr

Add a property to the state that will represent the selected block:

state: {
  opened: null,
  ...

Pass the corresponding blocks to the instances of the Trigger component: Also, the Trigger must know which block is open: To be able to assign a class to the button: When clicked, the block should be passed to the mutation: The mutation will set the value of the selected block:
toggleNav(state, block) {
  state.opened = state.opened === block ? null : block;
},

That is if it really toggle. If it's just a discovery, then it's enough state.opened = block(the name of the mutation in this case, of course, should be changed).
The mutation responsible for closing would look like this:
closeSidebarPanel(state) {
  state.opened = null;
},

The isNavOpen getter will also change:
isPanelOpen(state) {
  return !!state.opened;
},

And finally, you can display something in the Sidebar, for example:
But if Sidebar is designed specifically for these blocks, it would probably make more sense for him to know who is currently open. In the Sidebar you hook opened to the slot: Accordingly, in the parent component:
<template #default="{ block }">
  <div class="sidebar-panel-settings">
    <div class="setting-block">
      {{ block.bName }}
    </div>
  </div>
</template>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question