Dart Polymer: How to filter elements in repeat-template?

☆樱花仙子☆ 提交于 2019-12-20 14:09:26

问题


I'm using the repeat template of Dart Polymer to show the items of list. Now, I would like to implement a search filter, where only the items are displayed, which relates to the typed search term. Consider the following code:

my-element.html

<polymer-element name="my-element">
  <script type="application/dart" src="my-element.dart"></script>
  <template>
    <input type="text" value="{{ searchTerm }}">
    <ul>
      <template repeat="{{ item in items }}">
        <template if="{{ matchesSearchFilter(item) }}">
          <li>{{ item }}</li>
        </template>
      </template>
    </ul>
  </template>
</polymer-element> 

my-element.dart

@CustomTag('my-element')
class MyElement extends PolymerElement {
  @observable List<String> items = toObservable(["Monday", "Tuesday", "Wednesday"]);
  @observable String searchTerm = '';

  MyElement.created() : super.created();

  matchesSearchFilter(String item) {
    if (searchTerm.isEmpty) return true;
    return item.toLowerCase().contains(searchTerm.toLowerCase());
  }
} 

For example, when I type "Mo" in the textbox, I would expect that the list of items updates automatically, such that only "Monday" is shown. However on typing any search term, the list remains the same and the search term is ignored.

So, how to implement such a feature correctly?


回答1:


An second alternative is to add a filter :

  <template repeat="{{ item in items | filter(searchTerm)}}">
      <li>{{ item }}</li>
  </template>

and

// One line
filter(term) => (items) => term.isEmpty ? items : items.where((item) => item.toLowerCase().contains(searchTerm.toLowerCase())).toList();

Items will be filtered before being used in the repeat loop. Personally I prefer to use a filter instead of Günter's solution because :
- it's easy
- centralized
- quite understandable to add other filters with pipe operator
- your list is not changed (only filtered)

For example, imagine that you also want to sort your items. Then just add another filter :

<template repeat="{{ item in items | filter(searchTerm) | sort(sortField, sortAsc)}}">
      <li>{{ item }}</li>
</template>

Your items will be filtered and then sorted (each time searchTerm, sortField or sortAsc change). Easy ;-)

And the last tips: the previous code will filter your list at each keystroke which is not very user friendly!

Instead you can use that kind of code:

// Note that now I filter items on searchFilter and not more on searchTerm
<template repeat="{{ item in items | filter(searchFilter) | sort(sortField, sortAsc)}}">
      <li>{{ item }}</li>
</template>

And then in your class

@CustomTag('my-element')
class MyElement extends PolymerElement {

  @observable List<String> items = toObservable(["Monday", "Tuesday", "Wednesday"]);
  @observable String searchTerm = '';
  @observable String searchFilter = '';

  MyElement.created() : super.created();

  filter(term) => (items) => term.isEmpty ? items : items.where((item) => item.toLowerCase().contains(searchTerm.toLowerCase())).toList();

  // When the user keystroke, searchTerm is changed
  // Launch a Timer (if the timer was not null then stop it: it means the user has not finished
  // When the delay is elapsed then set searchFilter with searchTerm
  // As your filter use 'filter(searchFilter)' then your items will be filtered
  Timer _searchTimer;
  searchTermChanged(oldValue) {
    // If there's another keystroke during the delay then reset it
    if (_searchTimer != null) _searchTimer.cancel();
    new Timer(new Duration(milliSeconds: 300), () => searchFilter = searchTerm);
  }
} 



回答2:


An alternative solution would be to make a list allItems containing all items and when searchTerm changed update items like:

  @observable List<String> items = ['Monday', 'Tuesday', 'Wdnesday'];

  void searchTermChanged(oldVal) {
    items = items.where((String item) {
      if (searchTerm.isEmpty) return true;
      return item.toLowerCase().contains(searchTerm.toLowerCase());      
    }).toList(growable: false);
  }

In this case you shouldn't need the toObservable as it is redundant to observe if items are added or removed. To observe whether the items list was replaced the @observable attribut should be enough.



来源:https://stackoverflow.com/questions/21379167/dart-polymer-how-to-filter-elements-in-repeat-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!