diff --git a/src/store/modules/normalizers.js b/src/store/modules/normalizers.js
index 4fbfecae9b52658668980cdb1d275a6715789f32..c9dbc85075e09b19a1b45fde05db06ff2ac95f42 100644
--- a/src/store/modules/normalizers.js
+++ b/src/store/modules/normalizers.js
@@ -12,6 +12,10 @@ export const parseTuples = (tuples, key) => {
       accum[item.tuple[0]] = item.tuple[1]
     } else if (key === ':mascots') {
       accum[item.tuple[0]] = { ...item.tuple[1], id: `f${(~~(Math.random() * 1e8)).toString(16)}` }
+    } else if (item.tuple[0] === ':groups') {
+      accum[item.tuple[0]] = item.tuple[1].reduce((acc, group) => {
+        return [...acc, { [group.tuple[0]]: { value: group.tuple[1], id: `f${(~~(Math.random() * 1e8)).toString(16)}` }}]
+      }, [])
     } else if ((item.tuple[0] === ':sslopts' && item.tuple[1].length === 0) || // should be removed
       (item.tuple[0] === ':tlsopts' && item.tuple[1].length === 0)) {
       accum[item.tuple[0]] = {}
diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue
index b1624e5dac813d045938239cc2df3adfd7431030..024b4b7adc628487de82ceac190ff093a1e9bca6 100644
--- a/src/views/settings/components/Inputs.vue
+++ b/src/views/settings/components/Inputs.vue
@@ -55,30 +55,6 @@
       @input="update($event, settingGroup.group, settingGroup.key, settingParent, setting.key, setting.type, nested)">
       <template slot="prepend">:</template>
     </el-input>
-    <div v-if="editableKeywordWithInput(setting.key)">
-      <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input">
-        <el-input :value="key" placeholder="pattern" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> :
-        <el-input :value="value" placeholder="replacement" class="value-input" @input="parseEditableKeyword($event, 'value', index)"/>
-        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/>
-      </div>
-      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
-    </div>
-    <div v-if="editableKeywordWithSelect(setting.type)">
-      <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input">
-        <el-input :value="key" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> :
-        <el-select :value="value" multiple filterable allow-create class="value-input" @change="parseEditableKeyword($event, 'value', index)"/>
-        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/>
-      </div>
-      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
-    </div>
-    <div v-if="editableKeywordWithInteger(setting.type)">
-      <div v-for="([key, value], index) in editableKeywordData(data)" :key="index" class="setting-input">
-        <el-input :value="key" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', index)"/> :
-        <el-input-number :value="value" :min="0" size="large" class="value-input" @change="parseEditableKeyword($event, 'value', index)"/>
-        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(index)"/>
-      </div>
-      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
-    </div>
     <div v-if="setting.key === ':prune'">
       <el-radio-group v-model="prune">
         <el-radio label=":disabled">Disabled</el-radio>
@@ -137,8 +113,9 @@
         @input="updateSetting($event, settingGroup.group, settingGroup.key, setting.key)"/>
     </div>
     <!-- special inputs -->
-    <auto-linker-input v-if="settingGroup.group === ':auto_linker'" :setting-group="settingGroup" :setting="setting" :data="data"/>
-    <mascots-input v-if="setting.key === ':mascots'" :setting-group="settingGroup" :setting="setting" :data="data"/>
+    <auto-linker-input v-if="settingGroup.group === ':auto_linker'" :data="data" :setting-group="settingGroup" :setting="setting"/>
+    <mascots-input v-if="setting.key === ':mascots'" :data="data" :setting-group="settingGroup" :setting="setting"/>
+    <editable-keyword v-if="editableKeyword(setting.key, setting.type)" :data="data" :setting-group="settingGroup" :setting="setting"/>
     <!-------------------->
     <div v-if="setting.key === ':icons'">
       <div v-for="(icon, index) in iconsValue" :key="index" class="mascot-container">
@@ -165,13 +142,14 @@
 import AceEditor from 'vue2-ace-editor'
 import 'brace/mode/elixir'
 import 'default-passive-events'
-import { AutoLinkerInput, MascotsInput } from './inputComponents'
+import { AutoLinkerInput, EditableKeyword, MascotsInput } from './inputComponents'
 
 export default {
   name: 'Inputs',
   components: {
     editor: AceEditor,
     AutoLinkerInput,
+    EditableKeyword,
     MascotsInput
   },
   props: {
@@ -183,7 +161,7 @@ export default {
       required: false
     },
     data: {
-      type: Object || Array,
+      type: [Object, Array],
       default: function() {
         return {}
       }
@@ -287,43 +265,12 @@ export default {
   methods: {
     addIconToIcons() {},
     addValueToIcons() {},
-    addRowToEditableKeyword() {
-      const updatedValue = this.editableKeywordData(this.data).reduce((acc, el, i) => {
-        return { ...acc, [el[0]]: el[1] }
-      }, {})
-      this.updateSetting({ ...updatedValue, '': [] }, this.settingGroup.group, this.settingGroup.key, this.setting.key)
-    },
-    deleteEditableKeywordRow(index) {
-      const filteredValues = this.editableKeywordData(this.data).filter((el, i) => index !== i)
-      const updatedValue = filteredValues.reduce((acc, el, i) => {
-        return { ...acc, [el[0]]: el[1] }
-      }, {})
-      this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key)
-    },
     deleteIcondRow(index) {},
-    editableKeywordWithInput(key) {
-      return key === ':replace'
-    },
-    editableKeywordWithInteger(type) {
-      return Array.isArray(type)
-        ? type.includes('keyword') && type.includes('integer')
-        : false
-    },
-    editableKeywordWithSelect(type) {
-      return type === 'map' ||
-      (Array.isArray(type) && type.includes('keyword') && type.findIndex(el => el.includes('list') && el.includes('string')) !== -1)
-    },
-    editableKeywordData(data) {
-      return Object.keys(data).map(key => [key, data[key]])
-    },
-    parseEditableKeyword(value, inputType, index) {
-      const updatedValue = this.editableKeywordData(this.data).reduce((acc, el, i) => {
-        if (index === i) {
-          return inputType === 'key' ? { ...acc, [value]: el[1] } : { ...acc, [el[0]]: value }
-        }
-        return { ...acc, [el[0]]: el[1] }
-      }, {})
-      this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key)
+    editableKeyword(key, type) {
+      return key === ':replace' ||
+        (Array.isArray(type) && type.includes('keyword') && type.includes('integer')) ||
+        type === 'map' ||
+        (Array.isArray(type) && type.includes('keyword') && type.findIndex(el => el.includes('list') && el.includes('string')) !== -1)
     },
     parseIcons(value, inputType, index) {},
     parseRateLimiter(value, input, typeOfInput, typeOfLimit, currentValue) {
diff --git a/src/views/settings/components/inputComponents/EditableKeyword.vue b/src/views/settings/components/inputComponents/EditableKeyword.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f1f106cd862ea2cc1f98014725821f62da88da77
--- /dev/null
+++ b/src/views/settings/components/inputComponents/EditableKeyword.vue
@@ -0,0 +1,109 @@
+<template>
+  <div>
+    <div v-if="setting.key === ':replace'">
+      <div v-for="element in data" :key="getId(element)" class="setting-input">
+        <el-input :value="getKey(element)" placeholder="pattern" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
+        <el-input :value="getValue(element)" placeholder="replacement" class="value-input" @input="parseEditableKeyword($event, 'value', element)"/>
+        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/>
+      </div>
+      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
+    </div>
+    <div v-else-if="editableKeywordWithInteger">
+      <div v-for="element in data" :key="getId(element)" class="setting-input">
+        <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
+        <el-input-number :value="getValue(element)" :min="0" size="large" class="value-input" @change="parseEditableKeyword($event, 'value', element)"/>
+        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/>
+      </div>
+      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
+    </div>
+    <div v-else>
+      <div v-for="element in data" :key="getId(element)" class="setting-input">
+        <el-input :value="getKey(element)" placeholder="key" class="name-input" @input="parseEditableKeyword($event, 'key', element)"/> :
+        <el-select :value="getValue(element)" multiple filterable allow-create class="value-input" @change="parseEditableKeyword($event, 'value', element)"/>
+        <el-button icon="el-icon-minus" circle @click="deleteEditableKeywordRow(element)"/>
+      </div>
+      <el-button icon="el-icon-plus" circle @click="addRowToEditableKeyword"/>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'EditableKeyword',
+  props: {
+    data: {
+      type: [Object, Array],
+      default: function() {
+        return {}
+      }
+    },
+    setting: {
+      type: Object,
+      default: function() {
+        return {}
+      }
+    },
+    settingGroup: {
+      type: Object,
+      default: function() {
+        return {}
+      }
+    }
+  },
+  computed: {
+    editableKeywordWithInteger() {
+      return Array.isArray(this.setting.type) && this.setting.type.includes('keyword') && this.setting.type.includes('integer')
+    }
+  },
+  methods: {
+    addRowToEditableKeyword() {
+      const updatedValue = [...this.data, { '': { value: '', id: this.generateID() }}]
+      this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key)
+    },
+    deleteEditableKeywordRow(element) {
+      const deletedId = this.getId(element)
+      const filteredValues = this.data.filter(element => Object.values(element)[0].id !== deletedId)
+      this.updateSetting(filteredValues, this.settingGroup.group, this.settingGroup.key, this.setting.key)
+    },
+    generateID() {
+      return `f${(~~(Math.random() * 1e8)).toString(16)}`
+    },
+    getKey(element) {
+      return Object.keys(element)[0]
+    },
+    getId(element) {
+      const { id } = Object.values(element)[0]
+      return id
+    },
+    getValue(element) {
+      const { value } = Object.values(element)[0]
+      return value
+    },
+    parseEditableKeyword(value, inputType, element) {
+      const updatedId = this.getId(element)
+      const updatedValue = this.data.map((element, index) => {
+        if (Object.values(element)[0].id === updatedId) {
+          return inputType === 'key'
+            ? { [value]: Object.values(this.data[index])[0] }
+            : { [Object.keys(element)[0]]: { ...Object.values(this.data[index])[0], value }}
+        }
+        return element
+      })
+
+      this.updateSetting(updatedValue, this.settingGroup.group, this.settingGroup.key, this.setting.key, this.setting.type)
+    },
+    updateSetting(value, group, key, input, type) {
+      const updatedSettings = value.reduce((acc, element) => {
+        return { ...acc, [Object.keys(element)[0]]: [['list', 'string'], Object.values(element)[0].value] }
+      }, {})
+      this.$store.dispatch('UpdateSettings', { group, key, input, value: updatedSettings, type })
+      this.$store.dispatch('UpdateState', { group, key, input, value })
+    }
+  }
+}
+</script>
+
+<style rel='stylesheet/scss' lang='scss'>
+@import '../../styles/main';
+@include settings
+</style>
diff --git a/src/views/settings/components/inputComponents/index.js b/src/views/settings/components/inputComponents/index.js
index eb2d7b8364ad5486930bfb92a34dd468df619a8d..922dea1b592f2e5edaea9f1fee4650e7e2dc00b8 100644
--- a/src/views/settings/components/inputComponents/index.js
+++ b/src/views/settings/components/inputComponents/index.js
@@ -1,2 +1,3 @@
 export { default as AutoLinkerInput } from './AutoLinkerInput'
 export { default as MascotsInput } from './MascotsInput'
+export { default as EditableKeyword } from './EditableKeyword'