我们为应用程序中的一些典型网格用法实现了绑定(bind)。它工作得很好,除非你修改商店,例如添加一条记录,你会在 View 中看到 n + 两条相同的记录。 当我检查商店的状态时,它显示了 n + 1 个值。
就好像我有一个网格,其中显示了一条记录并调用:grid.getStore().add(modelFactory.createModel(event.getBean())); 我现在有:
第二行和第三行相等,不能选择第三行。此外,它不存在于 grid.getStore() 中。
来源:
freqsGrid = new AwesomeGridPanel() {
@Override
public void createColumns() {/**/}
};
freqBinding = AwesomeGridBinding.createGridBinding(freqsGrid, "frequencies");
简单的绑定(bind)源。它将模型的 List 属性按原样映射到网格。
public class AwesomeGridBinding {
public static FieldBinding createGridBinding(AwesomeGridPanel grid, String property) {
return new FieldBinding(new AwesomeGridAdapterField(grid), property);
}
}
class AwesomeGridAdapterField<T> extends AdapterField {
protected AwesomeGridPanel grid;
private StoreListener<BeanModel> storeChangedListener;
public AwesomeGridAdapterField(AwesomeGridPanel grid) {
super(grid);
this.grid = grid;
configureGrid(grid, this);
}
@Override
public void setValue(Object value) {
List data;
if (value == null)
data = new ArrayList<>();
else if (!(value instanceof List))
throw new IllegalArgumentException();
else
data = (List) value;
grid.getStore().setMonitorChanges(false);
grid.getStore().setFiresEvents(false);
setResults(grid.getStore(), data);
grid.getStore().setFiresEvents(true);
grid.getStore().setMonitorChanges(true);
如果我删除下面的行, View 将在添加后停止显示 n+2 行,并且甚至在 formBinding.bind(createModel(bean)); 之后开始显示添加的行到另一个 bean。
grid.getGrid().getView().refresh(false);
}
@Override
public Object getValue() {
List<T> result = new ArrayList<>();
for (BeanModel bm : grid.getStore().getModels())
if (isBeanForResult(bm))
result.add(extractResult(bm));
return result;
}
protected void setResults(ListStore<BeanModel> store, List data) {
store.removeAll();
for (Object obj : data)
if (obj instanceof BeanModel)
store.add((BeanModel) obj);
else
throw new IllegalArgumentException();
}
protected boolean isBeanForResult(BeanModel beanModel) {
return true;
}
protected T extractResult(BeanModel bmFromStore) {
return bmFromStore.getBean();
}
private final EventType[] STORE_EVENTS = {Store.Add, Store.Clear, Store.DataChanged, Store.Remove, Store.Update};
protected void configureGrid(final AwesomeGridPanel grid, final AdapterField field) {
grid.getStore().setMonitorChanges(true);
// grid.getStore().removeAllListeners();
if (storeChangedListener != null)
grid.getStore().removeStoreListener(storeChangedListener);
storeChangedListener = new StoreListener<BeanModel>() {
@Override
public void handleEvent(StoreEvent<BeanModel> e) {
super.handleEvent(e);
for (EventType se : STORE_EVENTS) {
if (se != e.getType())
continue;
field.fireEvent(Events.Change);
return;
}
}
};
grid.getStore().addStoreListener(storeChangedListener);
}
}
最佳答案
我发现解决问题的唯一方法是避免商店修改。 我使用了 BeanModel。
小部件:
schedulesGridPanel = new AwesomeGridView<RcTaskSchedule>(ListBinding.createEmptyStore(), NavigationTarget.RADIOCONTROL_TASK_DIALOG, "RCTaskDialogSchedulesGridPanel") {
@Override
public void createColumns() {...}
};
formBinding.addFieldBinding(new ListBinding(schedulesGridPanel.getGrid(), "schedules"));
...
@Override
public BeanModel getBeanModel() {
return (BeanModel) formBinding.getModel();
}
... 主持人:
eventBus.addBeanCreatedEventHandler(RcTaskSchedule.class, NavigationTarget.RC_TASK_SCHEDULE_DIALOG, new BeanCreatedEvent.Handler<RcTaskSchedule>() {
@Override
public void onBeanCreated(BeanCreatedEvent<RcTaskSchedule> event) {
ListBinding.addListItemInBeanModel(display.getBeanModel(), "schedules", schedulesFactory.createModel(event.getBean()));
}
});
eventBus.addBeanModifiedEventHandler(RcTaskSchedule.class, NavigationTarget.RC_TASK_SCHEDULE_DIALOG, new BeanModifiedEvent.Handler<RcTaskSchedule>() {
@Override
public void onBeanModified(BeanModifiedEvent<RcTaskSchedule> event) {
ListBinding.updateListItemInBeanModel(display.getBeanModel(), "schedules",
schedulesFactory.createModel(event.getOldBean()), schedulesFactory.createModel(event.getModifiedBean()));
}
});
...
public class ListBinding extends FieldBinding {
private Grid grid;
private ChangeListener listener = null;
private MemoryProxy memoryProxy = null;
public ListBinding(Grid grid, String property) {
super(new AdapterField(grid), property);
this.grid = grid;
if (!(grid.getStore().getLoader() instanceof BaseListLoader))
return;
BaseListLoader loader = (BaseListLoader) grid.getStore().getLoader();
if (!(loader.getProxy() instanceof MemoryProxy))
return;
memoryProxy = (MemoryProxy) loader.getProxy();
}
@Override
public void bind(ModelData model) {
super.bind(model);
if (memoryProxy == null)
return;
grid.getStore().removeAll();
memoryProxy.setData(getModel().get(getProperty()));
grid.getStore().getLoader().load();
if (!(model instanceof BeanModel))
return;
BeanModel bm = (BeanModel) model;
listener = new ChangeListener() {
@Override
public void modelChanged(ChangeEvent event) {
if (!(event instanceof PropertyChangeEvent))
return;
if (!property.equals(((PropertyChangeEvent) event).getName()))
return;
grid.getStore().removeAll();
memoryProxy.setData(getModel().get(getProperty()));
grid.getStore().getLoader().load();
}
};
bm.addChangeListener(listener);
}
@Override
public void unbind() {
super.unbind();
grid.getStore().removeAll();
if (listener == null)
return;
if (!(this.getModel() instanceof BeanModel))
return;
BeanModel bm = (BeanModel) this.getModel();
bm.removeChangeListener(listener);
}
public static ListStore<BeanModel> createEmptyStore() {
return new ListStore<>(new BaseListLoader(new MemoryProxy(new BoundList<>())/*, new BeanModelReader()*/));
}
public static void addListItemInBeanModel(BeanModel beanModel, String property, BeanModel newItem) {
if (beanModel == null || !(beanModel.get(property) instanceof List) || newItem == null)
return;
List<BeanModel> list = beanModel.get(property);
list.add(newItem);
beanModel.set(property, null);
beanModel.set(property, list);
}
public static void updateListItemInBeanModel(BeanModel beanModel, String property, BeanModel oldItem, BeanModel newItem) {
if (beanModel == null || !(beanModel.get(property) instanceof List) || newItem == null || oldItem == null)
return;
List<BeanModel> list = beanModel.get(property);
int index = list.indexOf(oldItem);
if (index < 0)
return;
list.set(index, newItem);
beanModel.set(property, list);
}
public static void removeListItemsInBeanModel(BeanModel beanModel, String property, List<BeanModel> items) {
if (beanModel == null || !(beanModel.get(property) instanceof List) || items == null || items.isEmpty())
return;
List<BeanModel> list = beanModel.get(property);
list.removeAll(items);
beanModel.set(property, list);
}
}
关于javascript - 网格的字段绑定(bind)。将新记录添加到 Store 后 View 仍然不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32582099/
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr