Upto now Extjs 6 sencha is not providing Tagfield for modern toolkit.
This kind of component we can use many places in current mobile apps based on client requirements. So i implemented the tagfield using picker and working as expected.
Preview:
Code snippet:
Ext.define('Ext.field.TagField', {
extend: 'Ext.field.Picker',
xtype: 'tagfield',
requires: [
'Ext.picker.Picker'
],
config: {
store: null,
displayField: 'text',
valueField: 'id',
picker: 'floated',
floatedPicker: {
xtype: 'list',
selectable: 'multi'
},
selected: {}
},
onSelect(t, recs) {
let i = 0,
len = recs.length;
if (!this._selected) {
this._selected = {};
}
while (i < len) {
this._selected[recs[i].get(this.getValueField())] = recs[i];
this.addTag(recs[i]);
i++;
}
},
onDeselect(t, recs) {
let i = 0,
len = recs.length;
while (i < len) {
delete this._selected[recs[i].get(this.getValueField())];
this.removeTag(recs[i]);
i++;
}
},
addTag(tag) {
var dispFld = this.getDisplayField();
var elId = this.id + '-tagId-' + tag.internalId;
let el = document.createElement('span');
el.id = elId;
el.innerHTML = `${tag.get( dispFld )} <span style="margin-left: 2px; color: red;" class="x-fa fa-times-circle" aria-hidden="true"> </span>`;
el.style.padding = '4px';
el.style.margin = '4px';
el.style.cursor = 'default';
el.style.backgroundColor = '#1E90FF';
el.style.borderRadius = '3px';
if (tag.tagCls) {
el.classList.add(tag.tagCls);
}
el.setAttribute('tagFieldSpan', true);
el.querySelector('span').addEventListener('click', function () {
this.getPicker().onItemDeselect([tag]);
this.getPicker().setItemSelection([tag], false);
}.bind(this));
this.beforeInputElement.append(el);
this.beforeInputElement.setStyle({
marginRight: '10px',
flexWrap: 'wrap'
});
let storedValues = this.getValue();
this.fireEvent('change', this, storedValues, this._selected);
storedValues = null;
},
removeTag(tag) {
let removed = tag.get(this.getValueField());
let el = this.beforeInputElement.down(`#${this.id}-tagId-${tag.internalId}`);
if (el) {
el.destroy();
}
if (!this.expanded) {
this.syncLabelPlaceholder(true);
}
let storedValues = this.getValue();
this.fireEvent('change', this, storedValues, this._selected, removed);
storedValues = null;
removed = null;
},
createFloatedPicker() {
const me = this;
let result = Ext.merge({
ownerCmp: me,
store: me.getStore(),
itemTpl: '{name}',
listeners: {
select: {
fn: me.onSelect,
scope: me
},
deselect: {
fn: me.onDeselect,
scope: me
}
}
}, me.getFloatedPicker());
return result;
},
getValue() {
var keys = Object.keys(this._selected),
i = 0,
len = keys.length,
values = [];
while (i < len) {
values.push(this._selected[keys[i]].get(this.getValueField()));
i++;
}
return values;
},
setValue(v) {
let selection = [];
if (!(v instanceof Array)) {
v = [v];
}
let i = 0,
len = v.length,
store = this.getPicker().getStore(),
f, me = this;
if (!store) {
return false;
}
if (!store.isLoaded()) {
store.addListener('load', () => {
me.setValue(v);
});
return false;
}
while (i < len) {
f = store.getAt(store.findExact(this.getValueField(), v[i]));
if (f) {
selection.push(f);
}
i++;
}
if (selection.length) {
this.getPicker().select(selection);
}
if (!this.expanded) {
this.syncLabelPlaceholder(true);
}
},
privates: {
syncLabelPlaceholder: function (val) {
let inside;
this._animPlaceholderLabel = val;
if (this.rendered) {
if (Object.keys(this._selected).length > 0) {
inside = false;
} else {
inside = !this.hasFocus || this.getDisabled() || this.getReadOnly();
}
this.setLabelInPlaceholder(inside);
}
this._animPlaceholderLabel = false;
},
},
isInputField: false,
isSelectField: true
});
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('Fiddle.view.MyPanel', {
extend: 'Ext.panel.Panel',
alias: 'TestPanelDataBinding',
viewModel: {
data: {
fName: 'HariKrishna Bura'
}
},
width: 400,
height: 300,
title: 'Form data',
items: [{
xtype: 'textfield',
bind: '{fName}',
width: 300,
label: 'Name'
}, {
xtype: 'tagfield',
multiSelect: true,
displayField: 'name',
valueField: 'id',
label: 'tag Field',
store: Ext.create('Ext.data.Store', {
data: [{
id: 1,
name: 'Hyderabad'
}, {
id: 2,
name: 'Bengaluru'
}, {
id: 3,
name: 'Chennai'
}]
})
}]
});
/*
tag or checkbox
*/
var pnl = Ext.create('Fiddle.view.MyPanel', {
fullscreen: true
});
}
});
You can access my fiddler for reference:
https://fiddle.sencha.com/#view/editor&fiddle/2sdu