Browse Source

Autocomplete: support scoped slot as custom template

Leopoldthecoder 7 years ago
parent
commit
a35ab0bb03

+ 8 - 33
examples/docs/en-US/input.md

@@ -1,18 +1,4 @@
 <script>
-  import Vue from 'vue';
-  Vue.component('my-item-en', {
-    functional: true,
-    render: function (h, ctx) {
-      var item = ctx.props.item;
-      return h('li', ctx.data, [
-        h('div', { attrs: { class: 'value' } }, [item.value]),
-        h('span', { attrs: { class: 'link' } }, [item.link])
-      ]);
-    },
-    props: {
-      item: { type: Object, required: true }
-    }
-  });
   export default {
     data() {
       return {
@@ -480,18 +466,21 @@ You can get some recommended tips based on the current input.
 
 Customize how suggestions are displayed.
 
-:::demo
+:::demo Use `scoped slot` to customize suggestion items. In the scope, you can access the suggestion object via the `item` key.
 ```html
 <el-autocomplete
   popper-class="my-autocomplete"
   v-model="state3"
   :fetch-suggestions="querySearch"
-  custom-item="my-item-en"
   placeholder="Please input"
   @select="handleSelect"
   icon="edit"
-  :on-icon-click="handleIconClick"
-></el-autocomplete>
+  :on-icon-click="handleIconClick">
+  <template scope="props">
+    <div class="value">{{ props.item.value }}</div>
+    <span class="link">{{ props.item.link }}</span>
+  </template>
+</el-autocomplete>
 
 <style>
   .my-autocomplete {
@@ -512,19 +501,6 @@ Customize how suggestions are displayed.
 </style>
 
 <script>
-  Vue.component('my-item-en', {
-    functional: true,
-    render: function (h, ctx) {
-      var item = ctx.props.item;
-      return h('li', ctx.data, [
-        h('div', { attrs: { class: 'value' } }, [item.value]),
-        h('span', { attrs: { class: 'link' } }, [item.link])
-      ]);
-    },
-    props: {
-      item: { type: Object, required: true }
-    }
-  });
   export default {
     data() {
       return {
@@ -536,7 +512,7 @@ Customize how suggestions are displayed.
       querySearch(queryString, cb) {
         var links = this.links;
         var results = queryString ? link.filter(this.createFilter(queryString)) : links;
-        // call callback function to return recommended data
+        // call callback function to return suggestion objects
         cb(results);
       },
       createFilter(queryString) {
@@ -681,7 +657,6 @@ Attribute | Description | Type | Options | Default
 | props | configuration options, see the following table | object | — | — |
 |icon | icon name | string | — | — |
 |value | binding value | string | — | — |
-|custom-item | component name of your customized suggestion list item | string | — | — |
 |fetch-suggestions | a method to fetch input suggestions. When suggestions are ready, invoke `callback(data:[])` to return them to Autocomplete | Function(queryString, callback) | — | — |
 | popper-class | custom class name for autocomplete's dropdown | string | — | — |
 | trigger-on-focus | whether show suggestions when input focus | boolean | — | true |

+ 7 - 32
examples/docs/zh-CN/input.md

@@ -1,18 +1,4 @@
 <script>
-  import Vue from 'vue';
-  Vue.component('my-item-zh', {
-    functional: true,
-    render: function (h, ctx) {
-      var item = ctx.props.item;
-      return h('li', ctx.data, [
-        h('div', { attrs: { class: 'name' } }, [item.value]),
-        h('span', { attrs: { class: 'addr' } }, [item.address])
-      ]);
-    },
-    props: {
-      item: { type: Object, required: true }
-    }
-  });
   export default {
     data() {
       return {
@@ -550,18 +536,21 @@ export default {
 
 可自定义输入建议的显示
 
-::: demo
+::: demo 使用`scoped slot`自定义输入建议的模板。该 scope 的参数为`item`,表示当前输入建议对象。
 ```html
 <el-autocomplete
   popper-class="my-autocomplete"
   v-model="state3"
   :fetch-suggestions="querySearch"
-  custom-item="my-item-zh"
   placeholder="请输入内容"
   @select="handleSelect"
   icon="edit"
-  :on-icon-click="handleIconClick"
-></el-autocomplete>
+  :on-icon-click="handleIconClick">
+  <template scope="props">
+    <div class="name">{{ props.item.value }}</div>
+    <span class="addr">{{ props.item.address }}</span>
+  </template>
+</el-autocomplete>
 
 <style>
 .my-autocomplete {
@@ -586,19 +575,6 @@ export default {
 </style>
 
 <script>
-  Vue.component('my-item-zh', {
-    functional: true,
-    render: function (h, ctx) {
-      var item = ctx.props.item;
-      return h('li', ctx.data, [
-        h('div', { attrs: { class: 'name' } }, [item.value]),
-        h('span', { attrs: { class: 'addr' } }, [item.address])
-      ]);
-    },
-    props: {
-      item: { type: Object, required: true }
-    }
-  });
   export default {
     data() {
       return {
@@ -838,7 +814,6 @@ export default {
 | disabled      | 禁用            | boolean         | — | false   |
 | props | 配置选项,具体见下表 | object | — | — |
 | value         | 必填值输入绑定值   | string  | — | — |
-| custom-item  | 通过该参数指定自定义的输入建议列表项的组件名 | string  | — | — |
 | fetch-suggestions | 返回输入建议的方法,仅当你的输入建议数据 resolve 时,通过调用 callback(data:[]) 来返回它  | Function(queryString, callback)  | — | — |
 | popper-class | Autocomplete 下拉列表的类名 | string | — | — |
 | trigger-on-focus | 是否在输入框 focus 时显示建议列表 | boolean | — | true |

+ 2 - 19
packages/autocomplete/src/autocomplete-suggestions.vue

@@ -12,23 +12,8 @@
         view-class="el-autocomplete-suggestion__list"
       >
         <li v-if="parent.loading"><i class="el-icon-loading"></i></li>
-        <template v-for="(item, index) in suggestions" v-else>
-          <li
-            v-if="!parent.customItem"
-            :class="{'highlighted': parent.highlightedIndex === index}"
-            @click="select(item)"
-          >
-            {{item[props.label]}}
-          </li>
-          <component
-            v-else
-            :class="{'highlighted': parent.highlightedIndex === index}"
-            @click="select(item)"
-            :is="parent.customItem"
-            :item="item"
-            :index="index">
-          </component>
-        </template>
+        <slot v-else>
+        </slot>
       </el-scrollbar>
     </div>
   </transition>
@@ -52,8 +37,6 @@
     },
 
     props: {
-      props: Object,
-      suggestions: Array,
       options: {
         default() {
           return {

+ 11 - 5
packages/autocomplete/src/autocomplete.vue

@@ -22,12 +22,18 @@
       </template>
     </el-input>
     <el-autocomplete-suggestions
-      :props="props"
       visible-arrow
       :class="[popperClass ? popperClass : '']"
-      ref="suggestions"
-      :suggestions="suggestions"
-    >
+      ref="suggestions">
+      <li
+        v-for="(item, index) in suggestions"
+        :key="index"
+        :class="{'highlighted': highlightedIndex === index}"
+        @click="select(item)">
+        <slot :item="item">
+          {{ item[props.label] }}
+        </slot>
+      </li>
     </el-autocomplete-suggestions>
   </div>
 </template>
@@ -156,7 +162,7 @@
         }
       },
       select(item) {
-        this.$emit('input', item[this.props.value]);
+        this.$emit('input', item[this.props.label]);
         this.$emit('select', item);
         this.$nextTick(_ => {
           this.suggestions = [];

+ 1 - 17
packages/table/src/table-column.js

@@ -263,23 +263,7 @@ export default {
     }
 
     column.renderCell = function(h, data) {
-      // 未来版本移除
-      if (_self.$vnode.data.inlineTemplate) {
-        renderCell = function() {
-          data._self = _self.context || data._self;
-          if (Object.prototype.toString.call(data._self) === '[object Object]') {
-            for (let prop in data._self) {
-              if (!data.hasOwnProperty(prop)) {
-                data[prop] = data._self[prop];
-              }
-            }
-          }
-          // 静态内容会缓存到 _staticTrees 内,不改的话获取的静态数据就不是内部 context
-          data._staticTrees = _self._staticTrees;
-          data.$options.staticRenderFns = _self.$options.staticRenderFns;
-          return _self.customRender.call(data);
-        };
-      } else if (_self.$scopedSlots.default) {
+      if (_self.$scopedSlots.default) {
         renderCell = () => _self.$scopedSlots.default(data);
       }
 

+ 1 - 6
packages/theme-chalk/src/autocomplete.scss

@@ -49,12 +49,7 @@
     }
 
     &.highlighted {
-      color: $--color-primary;
-    }
-
-    &:active {
-      background-color: $--color-primary;
-      color: $--color-white;
+      background-color: $--select-option-hover-background;
     }
 
     &.divider {

+ 2 - 8
test/unit/specs/autocomplete.spec.js

@@ -182,8 +182,8 @@ describe('Autocomplete', () => {
       expect(suggestionList[1].innerHTML === '上海市长宁区淞虹路661号');
       suggestionList[1].click();
       setTimeout(_ => {
-        expect(inputElm.value).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
-        expect(vm.state).to.be.equal('Hot honey 首尔炸鸡(仙霞路)');
+        expect(inputElm.value).to.be.equal('上海市长宁区淞虹路661号');
+        expect(vm.state).to.be.equal('上海市长宁区淞虹路661号');
         expect(spy.withArgs().calledOnce).to.be.true;
         expect(suggestions.style.display).to.be.equal('none');
         done();
@@ -324,12 +324,6 @@ describe('Autocomplete', () => {
         const suggestionsList = suggestions.querySelectorAll('.el-autocomplete-suggestion__list li');
         let highlightedItem = suggestionsList[11];
         expect(highlightedItem.className).to.be.equal('highlighted');
-
-        autocomplete.highlight(-5);
-        vm.$nextTick(_ => {
-          let highlightedItem = suggestionsList[0];
-          expect(highlightedItem.className).to.be.equal('highlighted');
-        });
         done();
       });
     }, 500);

+ 0 - 26
test/unit/specs/table.spec.js

@@ -622,32 +622,6 @@ describe('Table', () => {
       }, DELAY);
     });
 
-    it('inline-template', done => {
-      const vm = createVue({
-        template: `
-          <el-table :data="testData">
-            <el-table-column prop="name" inline-template>
-              <span>[{{ row.name }}]</span>
-            </el-table-column>
-            <el-table-column prop="release"/>
-            <el-table-column prop="director"/>
-            <el-table-column prop="runtime"/>
-          </el-table>
-        `,
-
-        created() {
-          this.testData = getTestData();
-        }
-      });
-
-      setTimeout(_ => {
-        const cells = toArray(vm.$el.querySelectorAll('.el-table__body-wrapper tbody tr td:first-child'));
-        expect(cells.map(n => n.textContent)).to.eql(getTestData().map(o => `[${o.name}]`));
-        destroyVM(vm);
-        done();
-      }, DELAY);
-    });
-
     it('render-header', done => {
       const vm = createVue({
         template: `