Browse Source

combo支持新增

zhouy 7 years ago
parent
commit
701a8062f6

+ 77 - 0
frontend/saas-web/app/view/core/form/RemoteCombo.js

@@ -0,0 +1,77 @@
+/**
+ * Created by UAS30 on 2018/10/11.
+ */
+Ext.define('saas.view.core.form.RemoteCombo', {
+    extend: 'Ext.form.field.ComboBox',
+    alias: 'widget.remotecombo',
+    queryMode: 'local',//只在组件加载的时候请求一次
+    initComponent: function() {
+        var me = this;
+        Ext.applyIf(this,{
+            store:this.setStore(this.reqUrl)
+        });
+        me.callParent(arguments);
+    },
+
+    setStore:function(v){
+       var me=this;
+       me.url='resources/json/combotest.json';
+       var store=Ext.create('Ext.data.Store',{
+           fields:['value','text'],
+           autoLoad: true,
+           proxy: {
+               type: 'ajax',
+               url: me.url,
+               reader: {
+                   type: 'array',
+                   rootProperty: 'data'
+               }
+           }
+       });
+       me.store=store;
+
+    },
+    createPicker: function() {
+
+        var me = this,
+            picker,
+            pickerCfg = Ext.apply({
+                xtype: 'boundlistadd',
+                id: me.id + '-picker',
+                pickerField: me,
+                selectionModel: me.pickerSelectionModel,
+                floating: true,
+                hidden: true,
+                store: me.getPickerStore(),
+                displayField: me.displayField,
+                preserveScrollOnRefresh: true,
+                tpl: me.tpl,
+                ariaSelectable: me.ariaSelectable,
+                addHandler:me.addHandler
+            }, me.listConfig, me.defaultListConfig);
+        picker = me.picker = Ext.widget(pickerCfg);
+        if (me.pageSize) {
+            picker.pagingToolbar.on('beforechange', me.onPageChange, me);
+        }
+
+        // We limit the height of the picker to fit in the space above
+        // or below this field unless the picker has its own ideas about that.
+        if (!picker.initialConfig.maxHeight) {
+            picker.on({
+                beforeshow: me.onBeforePickerShow,
+                scope: me
+            });
+        }
+        picker.getSelectionModel().on({
+            beforeselect: me.onBeforeSelect,
+            beforedeselect: me.onBeforeDeselect,
+            focuschange: me.onFocusChange,
+            scope: me
+        });
+
+        picker.getNavigationModel().navigateOnSpace = false;
+
+        return picker;
+    }
+});
+

+ 488 - 0
frontend/saas-web/app/view/core/view/BoundListAdd.js

@@ -0,0 +1,488 @@
+/**
+ * Created by UAS30 on 2018/10/11.
+ */
+Ext.define('saas.view.core.view.BoundListAdd', {
+    extend: 'Ext.view.View',
+    alias: 'widget.boundlistadd',
+    requires: [
+        'Ext.view.BoundListKeyNav',
+        'Ext.layout.component.BoundList'
+    ],
+
+    mixins: [
+        'Ext.mixin.Queryable'
+    ],
+
+    /**
+     * @cfg {Number} pageSize
+     * If greater than `0`, a {@link Ext.toolbar.Paging} is displayed at the bottom of the list and store
+     * queries will execute with page {@link Ext.data.operation.Read#start start} and
+     * {@link Ext.data.operation.Read#limit limit} parameters.
+     */
+    pageSize: 0,
+
+    /**
+     * @cfg {String} [displayField=""]
+     * The field from the store to show in the view.
+     */
+
+    /**
+     * @property {Ext.toolbar.Paging} pagingToolbar
+     * A reference to the PagingToolbar instance in this view. Only populated if {@link #pageSize} is greater
+     * than zero and the BoundList has been rendered.
+     */
+
+    /**
+     * @cfg baseCls
+     * @inheritdoc
+     */
+    baseCls: Ext.baseCSSPrefix + 'boundlist',
+
+    /**
+     * @cfg itemCls
+     * @inheritdoc
+     */
+    itemCls: Ext.baseCSSPrefix + 'boundlist-item',
+    listItemCls: '',
+
+    /**
+     * @cfg shadow
+     * @inheritdoc
+     */
+    shadow: false,
+
+    /**
+     * @cfg trackOver
+     * @inheritdoc
+     */
+    trackOver: true,
+
+    /**
+     * @cfg preserveScrollOnRefresh
+     * @inheritdoc
+     */
+    preserveScrollOnRefresh: true,
+    enableInitialSelection: false,
+    refreshSelmodelOnRefresh: true,
+
+    /**
+     * @cfg componentLayout
+     * @inheritdoc
+     */
+    componentLayout: 'boundlist',
+
+    /**
+     * @cfg navigationModel
+     * @inheritdoc
+     */
+    navigationModel: 'boundlist',
+
+    /**
+     * @cfg scrollable
+     * @inheritdoc
+     */
+    scrollable: true,
+
+    /**
+     * @property ariaEl
+     * @inheritdoc
+     */
+    ariaEl: 'listEl',
+
+    /**
+     * @cfg tabIndex
+     * @inheritdoc
+     */
+    tabIndex: -1,
+
+    /**
+     * @cfg childEls
+     * @inheritdoc
+     */
+    childEls: [
+        'listWrap', 'listEl'
+    ],
+
+    /**
+     * @cfg renderTpl
+     * @inheritdoc
+     */
+    renderTpl: [
+        '<div id="{id}-listWrap" data-ref="listWrap"',
+        ' class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
+        '<ul id="{id}-listEl" data-ref="listEl" class="', Ext.baseCSSPrefix, 'list-plain"',
+        '<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
+        '>',
+        '</ul>',
+        '</div>',
+        '{%',
+        'var pagingToolbar=values.$comp.pagingToolbar;',
+        'if (pagingToolbar) {',
+        'Ext.DomHelper.generateMarkup(pagingToolbar.getRenderTree(), out);',
+        '}',
+        '%}',
+        {
+            disableFormats: true
+        }
+    ],
+
+    /**
+     * @cfg {String/Ext.XTemplate} tpl
+     * A String or Ext.XTemplate instance to apply to inner template.
+     *
+     * {@link Ext.view.BoundList} is used for the dropdown list of
+     * {@link Ext.form.field.ComboBox}. To customize the template you can set the tpl on
+     * the combobox config object:
+     *
+     *     Ext.create('Ext.form.field.ComboBox', {
+     *         fieldLabel   : 'State',
+     *         queryMode    : 'local',
+     *         displayField : 'text',
+     *         valueField   : 'abbr',
+     *         store        : Ext.create('StateStore', {
+     *             fields : ['abbr', 'text'],
+     *             data   : [
+     *                 {"abbr":"AL", "name":"Alabama"},
+     *                 {"abbr":"AK", "name":"Alaska"},
+     *                 {"abbr":"AZ", "name":"Arizona"}
+     *                 //...
+     *             ]
+     *         }),
+     *         // Template for the dropdown menu.
+     *         // Note the use of the "x-list-plain" and "x-boundlist-item" class,
+     *         // this is required to make the items selectable.
+     *         tpl: Ext.create('Ext.XTemplate',
+     *             '<ul class="x-list-plain"><tpl for=".">',
+     *                 '<li role="option" class="x-boundlist-item">{abbr} - {name}</li>',
+     *             '</tpl></ul>'
+     *         ),
+     *     });
+     *
+     * Defaults to:
+     *
+     *     Ext.create('Ext.XTemplate',
+     *         '<ul><tpl for=".">',
+     *             '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
+     *         '</tpl></ul>'
+     *     );
+     *
+     */
+
+    // Override because on non-touch devices, the bound field
+    // retains focus so that typing may narrow the list.
+    // Only when the show is triggered by a touch does the BoundList
+    // get explicitly focused so that the keyboard does not appear.
+    /**
+     * @cfg focusOnToFront
+     * @inheritdoc
+     */
+    focusOnToFront: false,
+
+    /**
+     * @cfg alignOnScroll
+     * @inheritdoc
+     */
+    alignOnScroll: false,
+
+    initComponent: function() {
+        var me = this,
+            baseCls = me.baseCls,
+            itemCls = me.itemCls;
+
+        me.selectedItemCls = baseCls + '-selected';
+        if (me.trackOver) {
+            me.overItemCls = baseCls + '-item-over';
+        }
+        me.itemSelector = '.' + itemCls;
+
+        if (me.floating) {
+            me.addCls(baseCls + '-floating');
+        }
+
+        if (!me.tpl) {
+            // should be setting aria-posinset based on entire set of data
+            // not filtered set
+            me.generateTpl();
+        } else if (!me.tpl.isTemplate) {
+            me.tpl = new Ext.XTemplate(me.tpl);
+        }
+        me.pagingToolbar = me.createPagingToolbar();
+        me.callParent();
+    },
+
+    /**
+     * Allow tpl to be generated programmatically to respond to changes in displayField
+     * @private
+     */
+    generateTpl: function () {
+        var me = this;
+
+        me.tpl = new Ext.XTemplate(
+            '<tpl for=".">',
+            '<li role="option" unselectable="on" class="' + me.itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
+            '</tpl>'
+        );
+    },
+
+    /**
+     * Updates the display field for this view. This will automatically trigger
+     * an regeneration of the tpl so that the updated displayField can be used
+     * @param {String} displayField
+     */
+    setDisplayField: function (displayField) {
+        this.displayField = displayField;
+        this.generateTpl();
+    },
+
+    getRefOwner: function() {
+        return this.pickerField || this.callParent();
+    },
+
+    getRefItems: function() {
+        var result = this.callParent(),
+            toolbar = this.pagingToolbar;
+
+        if (toolbar) {
+            result.push(toolbar);
+        }
+        return result;
+    },
+
+    createPagingToolbar: function() {
+        var me = this;
+        console.log(me.addHandler);
+        return new Ext.Toolbar({
+            id: me.id + '-toolbar',
+            border: true,
+            ownerCt: me,
+            items:[{
+                text:'add',
+                handler:me.addHandler,
+                scope:me
+            }],
+            ownerLayout: me.getComponentLayout()
+        });
+    },
+
+    refresh: function() {
+        var me = this,
+            tpl = me.tpl;
+
+        // Allow access to the context for XTemplate scriptlets
+        tpl.field = me.pickerField;
+        tpl.store = me.store;
+        me.callParent();
+        tpl.field = tpl.store = null;
+
+        if (!me.ariaStaticRoles[me.ariaRole]) {
+            me.refreshAriaAttributes();
+        }
+
+        // The view selectively removes item nodes, so the toolbar
+        // will be preserved in the DOM
+    },
+
+    refreshAriaAttributes: function() {
+        var me = this,
+            store = me.store,
+            selModel = me.getSelectionModel(),
+            multiSelect, totalCount, nodes, node, record, index, i, len;
+
+        // When the store is filtered or paged, we want to let the Assistive Technology
+        // users know that there are more records than currently displayed. This is not
+        // a requirement when the whole dataset fits the DOM.
+        // Note that it is possible for the store to be filtered but not fit the DOM.
+        // In that case we use filtered count as the set size.
+        totalCount = store.isFiltered() ? store.getCount() : store.getTotalCount() || store.getCount();
+        nodes = me.getNodes();
+
+        multiSelect = me.pickerField && me.pickerField.multiSelect;
+
+        for (i = 0, len = nodes.length; i < len; i++) {
+            node = nodes[i];
+            record = null;
+
+            if (totalCount !== len) {
+                record = me.getRecord(node);
+                index = store.indexOf(record);
+
+                node.setAttribute('aria-setsize', totalCount);
+                node.setAttribute('aria-posinset', index);
+            }
+
+            // For single-select combos aria-selected must be undefined
+            if (multiSelect) {
+                record = record || me.getRecord(node);
+                node.setAttribute('aria-selected', selModel.isSelected(record));
+            }
+        }
+    },
+
+    bindStore: function(store, initial) {
+       // var toolbar = this.pagingToolbar;
+
+        this.callParent(arguments);
+       /* if (toolbar) {
+            toolbar.bindStore(store, initial);
+        }*/
+    },
+
+    /**
+     * A method that returns the inner template for displaying items in the list.
+     * This method is useful to override when using a more complex display value, for example
+     * inserting an icon along with the text.
+     *
+     * The XTemplate is created with a reference to the owning form field in the `field` property to provide access
+     * to context. For example to highlight the currently typed value, the getInnerTpl may be configured into a
+     * ComboBox as part of the {@link Ext.form.field.ComboBox#listConfig listConfig}:
+     *
+     *     listConfig: {
+     *         getInnerTpl: function() {
+     *             return '{[values.name.replace(this.field.getRawValue(), "<b>" + this.field.getRawValue() + "</b>")]}';
+     *         }
+     *     }
+     * @param {String} displayField The {@link #cfg!displayField} for the BoundList.
+     * @return {String} The inner template
+     */
+    getInnerTpl: function(displayField) {
+        return '{' + displayField + '}';
+    },
+
+    onShow: function() {
+        var field = this.pickerField;
+        this.callParent();
+
+        // If the input field is not focused, then focus it.
+        if (field && field.rendered && !field.hasFocus) {
+            field.focus();
+        }
+    },
+
+    afterComponentLayout: function(width, height, oldWidth, oldHeight) {
+        var field = this.pickerField;
+
+        this.callParent([width, height, oldWidth, oldHeight]);
+
+        // Bound list may change size, so realign on layout
+        // **if the field is an Ext.form.field.Picker which has alignPicker!**
+        if (field && field.alignPicker) {
+            field.alignPicker();
+        }
+    },
+
+    onItemSelect: function(record) {
+        var me = this,
+            node;
+
+        node = me.callParent([record]);
+
+        if (node) {
+            if (me.ariaSelectable) {
+                node.setAttribute('aria-selected', 'true');
+            }
+            else {
+                node.removeAttribute('aria-selected');
+            }
+        }
+
+        return node;
+    },
+
+    onItemDeselect: function(record) {
+        var me = this,
+            node;
+
+        node = me.callParent([record]);
+
+        if (node && me.ariaSelectable) {
+            if (me.pickerField && me.pickerField.multiSelect) {
+                node.setAttribute('aria-selected', 'false');
+            }
+            else {
+                node.removeAttribute('aria-selected');
+            }
+        }
+
+        return node;
+    },
+
+    // Clicking on an already selected item collapses the picker
+    onItemClick: function(record) {
+        // The selection change events won't fire when clicking on the selected element. Detect it here.
+        var me = this,
+            field = me.pickerField,
+            valueField, selected;
+
+        if (!field) {
+            return;
+        }
+
+        valueField = field.valueField;
+        selected = me.getSelectionModel().getSelection();
+
+        if (!field.multiSelect && selected.length) {
+            selected = selected[0];
+            // Not all pickerField's have a collapse API, i.e. Ext.ux.form.MultiSelect.
+            if (selected && field.isEqual(record.get(valueField), selected.get(valueField)) && field.collapse) {
+                field.collapse();
+            }
+        }
+    },
+
+    onContainerClick: function(e) {
+        var toolbar = this.pagingToolbar,
+            clientRegion;
+
+        // Ext.view.View template method
+        // Do not continue to process the event as a container click if it is within the pagingToolbar
+        if (toolbar && toolbar.rendered && e.within(toolbar.el)) {
+            return false;
+        }
+
+        // IE10 and IE11 will fire pointer events when user drags listWrap scrollbars,
+        // which may result in selection being reset.
+        if (Ext.isIE10 || Ext.isIE11) {
+            clientRegion = this.listWrap.getClientRegion();
+
+            if (!e.getPoint().isContainedBy(clientRegion)) {
+                return false;
+            }
+        }
+    },
+
+    doDestroy: function() {
+        this.pagingToolbar = Ext.destroy(this.pagingToolbar);
+
+        this.callParent();
+    },
+
+    privates: {
+        /**
+         * @method getNodeContainer
+         * @private
+         * @inheritdoc
+         */
+        getNodeContainer: function() {
+            return this.listEl;
+        },
+
+        getTargetEl: function() {
+            return this.listEl;
+        },
+
+        getOverflowEl: function() {
+            return this.listWrap;
+        },
+
+        // Do the job of a container layout at this point even though we are not a Container.
+        finishRenderChildren: function () {
+            var toolbar = this.pagingToolbar;
+
+            this.callParent(arguments);
+
+            if (toolbar) {
+                toolbar.finishRender();
+            }
+        }
+    }
+});