grobian 666
grobian 666

Reputation: 33

w2ui filter option "contains not" possible?

I am using w2ui (1.5) and I would be interested in whether it is possible to use a filter that only delivers negative results

That means only records/keys which not fullfilling a certain criteria.

Like a condition "contains not" or "is not" in addition to

http://w2ui.com/web/docs/1.5/w2grid.textSearch.

Thanks! Gordon

Upvotes: 0

Views: 403

Answers (2)

Martin Stejskal
Martin Stejskal

Reputation: 11

I coded my own solution to this problem. This adds a way to use "not" for string and "!=" for number searches.

This function does the search and it is also used to store the grid advanced search popup in history state.

I'm sure this can be even more optimized, so please use this more like a guideline. Hope this helps somebody.

function searchExtend(event, grid) {
  // if event is null, we do just the local search
  var searchObj;
  if (event == null) {
    searchObj = grid;
  } else {
    searchObj = event;
  }

  // make a copy of old data
  const oldSearchData = structuredClone(searchObj.searchData);
  const oldSearchLogic = structuredClone(searchObj.searchLogic);
  var searchData = searchObj.searchData;
  var invertedSdata = [];

  var toSplice = [];
  // check operator if it's "not" or "!="
  for (var i = 0; i < searchData.length; i++) {
    var sdata = searchData[i];
    // invert the condition
    if (sdata.operator == "not") {
      toSplice.push(i);
      invertedSdata.push({
        field: sdata.field,
        type: sdata.type,
        operator: "contains",
        value: sdata.value
      });
    }

    if (sdata.operator == "!=") {
      toSplice.push(i);
      invertedSdata.push({
        field: sdata.field,
        type: sdata.type,
        operator: "=",
        value: sdata.value
      });
    }
  }

  // remove all "not" and "!=" from searchData
  for (var i in toSplice) {
    searchData.splice(i, 1);
  }

  var foundIds = [];

  // use inverted criteria to search
  if (invertedSdata.length > 0) {
    grid.searchData = invertedSdata;
    grid.searchLogic = "OR";

    grid.localSearch();
    grid.searchLogic = oldSearchLogic;
    // store found ids
    foundIds = structuredClone(grid.last.searchIds);
  }

  if (foundIds.length > 0) {
    // perform a search with original criteria - spliced "not" and "!="
    grid.searchData = searchData;
    grid.localSearch();
    var allRecIds = structuredClone(grid.last.searchIds);

    // if there's not any results, push push all recIds
    if (grid.last.searchIds.length == 0) {
      for (let i = 0; i < grid.records.length; i++) {
        allRecIds.push(i);
      }

    }

    // remove all ids found with inverted criteria from results. This way we do the "not" search
    for (const id of foundIds) {
      allRecIds.splice(allRecIds.indexOf(id), 1);
    }

    if (event != null) {
      // let the search finish, then refresh grid
      event.onComplete = function() {
        refreshGrid(grid, allRecIds, oldSearchData);
        setSearchState(grid);
      }
    } else {
      // refresh the grid
      refreshGrid(grid, allRecIds, oldSearchData);
      setSearchState(grid);
    }

    return;
  }

  if (event != null) {
    event.onComplete = function() {
      setSearchState(grid); // store state
    }
  } else {
    // refresh whole grid
    refreshGrid(grid, allRecIds, oldSearchData);
    setSearchState(grid);
  }
}

function refreshGrid(grid, allRecIds, oldSearchData) {
  grid.last.searchIds = allRecIds;
  grid.total = grid.last.searchIds.length;
  grid.searchData = oldSearchData;
  grid.refresh();
}

function setSearchState(grid) {
  history.replaceState(JSON.stringify(grid.searchData), "Search");
}

To use this, you have to call it from the grid's onSearch:

onSearch: function(event) {
      searchExtend(event, w2ui["grid"]);
    }

Also, if you want to use the history.state feature, it needs to be called from onLoad function:

onLoad: function(event) {
      event.onComplete = function() {
        console.log("History state: " + history.state);
        if (history.state != null) {
          w2ui["grid"].searchData = JSON.parse(history.state);
          searchExtend(null, w2ui["grid"]);
        }
    }

To add operators, please use this reference.

This is my solution to the problem:

operators: {
      'text': ['is', 'begins', 'contains', 'ends', 'not'], // could have "in" and "not in"
      'number': ['=', 'between', '>', '<', '>=', '<=', '!='],
      'date': ['is', 'between', {
        oper: 'less',
        text: 'before'
      }, {
        oper: 'more',
        text: 'after'
      }],
      'list': ['is'],
      'hex': ['is', 'between'],
      'color': ['is', 'begins', 'contains', 'ends'],
      'enum': ['in', 'not in']
    }

Upvotes: 0

grobian 666
grobian 666

Reputation: 33

okay, a possible solution is w2ui['grid'].search([{ field: var1, value: var2, operator: 'not in'}], 'OR');

Upvotes: 0

Related Questions