Angular 如果使用SelectionOptions,如何使用材质下拉选择进行更改检测

Angular 如果使用SelectionOptions,如何使用材质下拉选择进行更改检测,angular,dart,material-design,angular-material2,Angular,Dart,Material Design,Angular Material2,我有一个材质下拉选择的以下实现,它工作得很好 <material-dropdown-select [buttonText]="organizer?.name"> <material-select-item *ngFor="let sailingClub of sailingClubs" {{sailingClub.name}} </material-select-item> </material-dropdown-select> 并访问

我有一个材质下拉选择的以下实现,它工作得很好

<material-dropdown-select [buttonText]="organizer?.name">
  <material-select-item *ngFor="let sailingClub of sailingClubs"
    {{sailingClub.name}}
  </material-select-item>
</material-dropdown-select>
并访问name属性

ItemRenderer<SailingClub> displayNameRenderer = (SailingClub item) => item.name;
ItemRenderer displayNameRenderer=(帆船俱乐部项目)=>item.name;

您是否正在收听Firebase数据库的更改

我不确定什么是
\u store
或它的任何属性,但在Firebase中,您可以监听更改并更新选择选项。然后,“更改检测”应检测到选择选项已更改

sailingClubsRef.onValue((值){
filteredSailingClubs=新字符串选择选项(
value.snapshot.val(),
toFilterableString:displayNameRenderer,
);  
});

这是我目前的做法。将其作为答案发布,以提高可读性

首先,我必须为计算值添加新变量,并手动跟踪更改

StringSelectionOptions<SailingClub> filteredSailingClubs;
SelectionModel<SailingClub> singleSelectModel;
Map<String, SailingClub> oldSailingClubs;
SailingClub oldOrganizer;
为了最终能够更新filteredSailingClubs,我必须添加这个

void ngDoCheck() {
  if (oldSailingClubs != _store.state.sailingClubs) {
    oldSailingClubs = _store.state.sailingClubs;
    filteredSailingClubs =
        new StringSelectionOptions(_store.state.sailingClubs.values, toFilterableString: displayNameRenderer);
  }
  if (oldOrganizer != organizer) {
    oldOrganizer = organizer;
    singleSelectModel = new SelectionModel<SailingClub>.withList(selectedValues: [organizer]);
    singleSelectModel.selectionChanges.listen(update);
  }
}
void ngDoCheck(){
如果(旧帆船俱乐部!=\u store.state.sailingClubs){
oldSailingClubs=\u store.state.sailingClubs;
过滤式抽油杆=
新的StringSelectionOptions(\ u store.state.sailingClubs.values,toFilterableString:displayNameRenderer);
}
if(oldOrganizer!=组织者){
oldOrganizer=组织者;
singleSelectModel=new SelectionModel.withList(selectedValues:[organizer]);
singleSelectModel.selectionChanges.listen(更新);
}
}
这里还有一个回调,它允许我在gui中更改选择时更新一个值

void update(List<SelectionChangeRecord> record) {
  if (record.isNotEmpty && record.first.added.isNotEmpty) {
    onOrganizerChanged(record.first.added.first);
  }
}
void更新(列表记录){
if(record.isNotEmpty&&record.first.added.isNotEmpty){
OnOrganizationChanged(record.first.added.first);
}
}
不幸的是,这是许多锅炉板代码,只是为了使列表可搜索。之前,所有的变化检测都是通过角度和完全隐藏来处理的。因此,我怀疑我是否做错了

我也不想改变我商店的结构。它基本上是一个redux模式存储(使用greencat),并且是不可变的。 我也不想让我的商店知道任何关于gui或selectionmodel等的信息


我的下一步是从“材质”下拉列表中选择它自己,看看是否可以隐藏复杂性。

好,这是我的最终解决方案。在我看来,这并不是很好,因为它仍然需要一些代码,但至少它工作得很好。 代码量大的主要原因是map.values列表本身不稳定。因此,map.values与旧值的每次新比较都将返回true。即使地图没有改变。因此,我们必须保存原始地图

StringSelectionOptions<SailingClub> _filteredSailingClubs;
Map<String, SailingClub> _oldSailingClubs;
SelectionModel<SailingClub> _singleSelectModel;
SailingClub _oldOrganizer;
StreamSubscription _selectionListener;

StringSelectionOptions<SailingClub> get filteredSailingClubs {
  // We have to save the old state since the Iterable itself is unstable and would change all the time
  if (_oldSailingClubs != _store.state.sailingClubs) {
    _oldSailingClubs = _store.state.sailingClubs;
    _filteredSailingClubs =
      new StringSelectionOptions(_store.state.sailingClubs.values, toFilterableString: displayNameRenderer);
  }
  return _filteredSailingClubs;
}

SelectionModel<SailingClub> get singleSelectModel {
  // We have to update the selection model on organizer change
  if (_singleSelectModel == null || _oldOrganizer != organizer) {
    _oldOrganizer = organizer;
    _singleSelectModel = new SelectionModel<SailingClub>.withList(selectedValues: [organizer]);
    _selectionListener?.cancel();
    _selectionListener = _singleSelectModel.selectionChanges.listen(update);
  }
  return _singleSelectModel;
}
StringSelectionOptions\u filteredSailingClubs;
地图-古老的帆船俱乐部;
选择模型_singleSelectModel;
帆船俱乐部;
StreamSubscription\u selectionListener;
StringSelectionOptions获得筛选SailingClub{
//我们必须挽救旧的状态,因为Iterable本身是不稳定的,并且会一直变化
如果(_oldSailingClubs!=_store.state.sailingClubs){
_oldSailingClubs=\u store.state.sailingClubs;
_过滤式抽油杆=
新的StringSelectionOptions(\ u store.state.sailingClubs.values,toFilterableString:displayNameRenderer);
}
返回(u filteredSailingClubs);;
}
SelectionModel获取singleSelectModel{
//我们必须在组织者变更时更新选择模型
if(_singleSelectModel==null | | | u oldOrganizer!=organizer){
_oldOrganizer=组织者;
_singleSelectModel=new SelectionModel.withList(selectedValues:[organizer]);
_selectionListener?.cancel();
_selectionListener=\u singleSelectModel.selectionChanges.listen(更新);
}
返回单选择模型;
}

我自己还没有使用Firebase,也不知道它会返回什么样的值。我想你需要先听更新,然后做一些类似的事情,比如
filteredSailingClubs.optionGroups=[newoptiongroup(\u store.state.sailingClubs.values)]
两个简单的问题:你的商店对象有办法听对它的更改吗?类似于类存储{Stream get onstorechange=>…},状态的
sailingClubs
属性是映射、列表还是其他什么?您使用的是什么更改检测策略?如果你改变它,它能工作吗?谢谢你对我的问题感兴趣。关于商店对象。它就像一个redux商店(使用greencat库)。state变量本身是一个普通类,内部有几个映射。在发生更改时,将复制类,并将更改的映射作为输入。因此,旧的状态永远不会改变,但会创建一个新的状态。因此,我也没有任何流程,甚至没有改变策略。在进行更改时,只更新store.state变量,常规材质组件只需重新绘制自己的更改。只有带有搜索的下拉菜单不起作用,因为它无法拾取更改。我现在添加了一个答案来显示我当前的方法。我的商店本身是一个redux商店,它不了解gui。firebase回调也不知道任何有关gui的信息,例如StringSelection。它只是创建一个新事件,向存储发送更改。它适用于所有gui组件,包括下拉选择,除非我必须使用搜索api。为什么需要一个try语句,为什么不记录它捕获的任何内容?为了简洁起见,你把它省略了吗?您应该在创建新模型和新订阅之前取消以前对selectionChanges的订阅,这可能是破坏代码的问题之一。感谢您提供取消以前订阅的提示,我将实现这一点。之所以使用try-catch,是因为组织者可以为null,所以我需要更好地检查这种情况,我只是添加了try-catch以快速验证概念。但这不是我的代码的问题。问题是,如何使材质下拉列表了解更改。我的解决方案是可行的,但它是s
filteredSailingClubs = new StringSelectionOptions(_store.state.sailingClubs.values, toFilterableString: displayNameRenderer);
void ngDoCheck() {
  if (oldSailingClubs != _store.state.sailingClubs) {
    oldSailingClubs = _store.state.sailingClubs;
    filteredSailingClubs =
        new StringSelectionOptions(_store.state.sailingClubs.values, toFilterableString: displayNameRenderer);
  }
  if (oldOrganizer != organizer) {
    oldOrganizer = organizer;
    singleSelectModel = new SelectionModel<SailingClub>.withList(selectedValues: [organizer]);
    singleSelectModel.selectionChanges.listen(update);
  }
}
void update(List<SelectionChangeRecord> record) {
  if (record.isNotEmpty && record.first.added.isNotEmpty) {
    onOrganizerChanged(record.first.added.first);
  }
}
StringSelectionOptions<SailingClub> _filteredSailingClubs;
Map<String, SailingClub> _oldSailingClubs;
SelectionModel<SailingClub> _singleSelectModel;
SailingClub _oldOrganizer;
StreamSubscription _selectionListener;

StringSelectionOptions<SailingClub> get filteredSailingClubs {
  // We have to save the old state since the Iterable itself is unstable and would change all the time
  if (_oldSailingClubs != _store.state.sailingClubs) {
    _oldSailingClubs = _store.state.sailingClubs;
    _filteredSailingClubs =
      new StringSelectionOptions(_store.state.sailingClubs.values, toFilterableString: displayNameRenderer);
  }
  return _filteredSailingClubs;
}

SelectionModel<SailingClub> get singleSelectModel {
  // We have to update the selection model on organizer change
  if (_singleSelectModel == null || _oldOrganizer != organizer) {
    _oldOrganizer = organizer;
    _singleSelectModel = new SelectionModel<SailingClub>.withList(selectedValues: [organizer]);
    _selectionListener?.cancel();
    _selectionListener = _singleSelectModel.selectionChanges.listen(update);
  }
  return _singleSelectModel;
}