【问题标题】:Vue : Table filter on column name with conditionVue:带有条件的列名的表过滤器
【发布时间】:2018-06-23 11:02:09
【问题描述】:

我有以下代码来过滤表格。我从age 之类的下拉列表中选择一列,然后从< 之类的另一个下拉列表中选择运算符并搜索20 之类的输入,并希望在它们上搜索表。

过滤器:

// Select column name
<select class="dv-header-select" v-model="query.search_column">
    <option v-for="column in columns" :value="column">{{column}}</option>
</select>

// Select condition(<,>,<=,>=) 
<select class="dv-header-select" v-model="query.search_operator">
    <option v-for="(value, key) in operators" :value="key">{{value}}</option>
</select>

// Search value
<input type="text" class="dv-header-input" placeholder="Search"
    v-model="query.search_input">

请阅读 JS 部分中的代码 cmets 了解。

  <tr v-for="row in getSearchedRow">
      <td v-for="(value, key) in row">{{value}}</td>
  </tr>

JS:

  data() {
    return {
    model: { data: [] },
    // populating on API call
    columns: {},
    query: {
        search_column: 'id',
        search_operator: 'equal',
        search_input: ''
    }
  },

  getSearchedRow: function() {

    return this.model.data.filter(row => {
      let value = row[this.query.search_column];
      for(var key in row){
        if(String(row[key]).indexOf(this.query.search_input) !== -1){

          // Return true required to populate table
          if(this.query.search_column.length < 1) {
            return true;
          }

          // when condition gets here, The table shows 0 records
          if(this.query.search_operator == 'less_than') {
            return value < this.query.search_input;
          }

        }
      }
    });
  }

表格因第一个 if() 而被填充,但第二个 if() 显示为空。

我错过了什么?

【问题讨论】:

  • 此时valuethis.query.search_input 的实际值是多少?可能是您试图将两者作为数字进行比较,但它们实际上是字符串?著名的 "2"&gt;"10" 在 Javascript 中返回 true
  • @sjaustirni value 的值是选定的表列值。目前就像我只有三行一样,当您选择一列例如 id 时,值是22,23,24..... 而this.query.search_input 是我要搜索的搜索字符串,例如,从下拉列表中选择的列是 age,从下拉列表中选择的条件是 &gt;this.query.search_input 是 20。
  • 您是否会通过将strings 解析为int 来确保这两个变量都是数字并报告它是否有帮助?这可能会有所帮助:stackoverflow.com/questions/5630123/…
  • 不,它不适用于stringint
  • 嗯。由于我缺乏上下文知识,我看不出哪里可能出错。你能举一个这种行为的 MCVE 例子吗?

标签: javascript object search vue.js


【解决方案1】:

您不需要遍历对象的每个键并测试它们是否部分匹配所需的值。您可能可以将过滤器简化为这样的内容

getSearchedRow: function() {
    if (this.query.search_column === '')
        return this.model.data;

    return this.model.data.filter(row => {
        const value = row[this.query.search_column];

        // adapt to what your actual operators do
        switch (this.query.search_operator) {
            case 'less_than': return value < this.query.search_input;
            case 'more_than': return value > this.query.search_input;
            // and so on
            default: return false;
        }
    });
}

请注意,如果您想获得准确的结果,您可能必须使用一种机制将您的值转换为数字。例如:

data() {
    return {
        model: { data: [
            {id: 1, x: "a", age: 18},
            {id: 2, x: "a", age: 19},
            {id: 3, x: "b", age: 22},
            {id: 4, x: "b", age: 20},
        ] },
        columns: {
          id: {
              cast: function(v) {
                  return +v;
              }
          },
          age: {
              cast: function(v) {
                  return +v;
              }
          }
        },
        query: {
            search_column: 'age',
            search_operator: 'equal',
            search_input: ""
        }
    };
},

computed: {
    getSearchedRow: function() {
        if (this.query.search_column === '')
          return this.model.data;

        const col = this.query.search_column;
        const requiredval = (this.columns[col] && this.columns[col].cast) ? this.columns[col].cast(this.query.search_input) : this.query.search_input;

        return this.model.data.filter(row => {
            const value = row[col];

            switch (this.query.search_operator) {
                case 'less_than': return value < requiredval;
                case 'more_than': return value > requiredval;
                case 'equal': return value === requiredval;

                default: return false;
            }
        });
    }
}

还有一个演示

new Vue({
    el: '#app',
    data() {
        return {
            model: { data: [
                {id: 1, x: "a", age: 18},
                {id: 2, x: "a", age: 19},
                {id: 3, x: "b", age: 22},
                {id: 4, x: "b", age: 20},
            ] },
            columns: {
              id: {
                  cast: function(v) {
                      return +v;
                  }
              },
              age: {
                  cast: function(v) {
                      return +v;
                  }
              }
            },
            query: {
                search_column: 'age',
                search_operator: 'equal',
                search_input: ""
            }
        };
    },

    computed: {
        getSearchedRow: function() {
            if (this.query.search_column === '')
              return this.model.data;
        
            const col = this.query.search_column;
            const requiredval = (this.columns[col] && this.columns[col].cast) ? this.columns[col].cast(this.query.search_input) : this.query.search_input;
            
            return this.model.data.filter(row => {
                const value = row[col];
                
                switch (this.query.search_operator) {
                    case 'less_than': return value < requiredval;
                    case 'more_than': return value > requiredval;
                    case 'equal': return value === requiredval;
                    
                    default: return false;
                }
            });
        }
    }
});
<script src="https://unpkg.com/vue"></script>


<div id="app">
  <select class="dv-header-select" v-model="query.search_column">
      <option value="">Everything</option>
      <option value="id">ID</option>
      <option value="age">Age</option>
      <option value="x">X</option>
  </select>


  <select class="dv-header-select" v-model="query.search_operator">
      <option value="equal">=</option>
      <option value="less_than">&lt;</option>
      <option value="more_than">&gt;</option>
  </select>

<input type="text" class="dv-header-input" placeholder="Search"
    v-model="query.search_input">

  <table>
    <tr v-for="row in getSearchedRow">
        <td v-for="(value, key) in row">{{value}}</td>
    </tr>
  </table>
</div>

【讨论】:

    【解决方案2】:

    function filter(rows, query) {
      return rows.filter(r => {
        if (query.input.length < 1) {
          return true
        }
    
        if (query.col.length < 1) {
          return true
        }
    
        const v = r[query.col]
        const i = query.input
        switch (query.op) {
          case '=':
            return v == i
          case '<':
            return v < i
          case '>':
            return v > i
          case '<=':
            return v <= i
          case '>=':
            return v >= i
          default:
            throw "unreachable"
        }
      })
    }
    
    const rows = [{
      id: 1,
      age: 20
    }, {
      id: 2,
      age: 30
    }]
    console.log(filter(rows, {
      col: 'id',
      op: '=',
      input: '2'
    }))
    console.log(filter(rows, {
      col: 'age',
      op: '<',
      input: '25'
    }))
    console.log(filter(rows, {
      col: '',
      op: '<',
      input: '25'
    }))
    console.log(filter(rows, {
      col: 'id',
      op: '<',
      input: ''
    }))

    我认为您的过滤逻辑错误。也许你可以试试这个。

    【讨论】:

      猜你喜欢
      • 2021-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      相关资源
      最近更新 更多