java - 在 Wicket 口中正确刷新包含面板的表格

标签 java html refresh wicket panel

我有一个包含表格的 Wicket 口面板。这是它的构造函数:

public NotFinishedExamsPanel(String id, final String userId, String[] egal) {
    super(id, new ResourceModel("notFinishedExams"), true);

    this.setOutputMarkupId(true);

    MySystem mysystem = ((MySession) Session.get()).getMySystem();
    String uid = ((MySession) Session.get()).getUsername();

    ArrayList<ExamData> exams = new ArrayList<ExamData>();
    try {
        if (!mysystem.account(userId).isStudent()) {
            return;
        }

        for (String exId : mysystem.exams()) {
            Exam ex = mysystem.exam(exId);
            if ((!(ex.hasResult(mysystem.account(userId).student().id()) && (ex.isPublished())))) {
                exams.add(new ExamData(mysystem.account(userId).student().id(), exId));
            }
        }

        ExamProvider exProv = new ExamProvider(exams);
        ArrayList<IColumn<ExamData, String>> columns = new ArrayList<IColumn<ExamData, String>>();
        columns.add(new PropertyColumn<ExamData, String>(new ResourceModel("title", "Titel"), "title"));
        columns.add(new PropertyColumn<ExamData, String>(new ResourceModel("date", "Datum"), "date"));
        columns.add(new PropertyColumn<ExamData, String>(new ResourceModel("time", "Uhrzeit"), "time"));
        columns.add(new PropertyColumn<ExamData, String>(new ResourceModel("location", "Ort"), "location"));
        columns.add(new PropertyColumn<ExamData, String>(new ResourceModel("status", "Status"), "status") {
            private static final long serialVersionUID = 7758862055950720446L;
            public void populateItem(Item item, String componentId, IModel rowModel) {
                Status status = ((ExamData) rowModel.getObject()).status;
                item.add(new ShowExamStatusPanel(componentId, status));
            }
        });
        columns.add(new PropertyColumn<ExamData, String>(new Model<String>(""), "status") {
            private static final long serialVersionUID = 7758862055950720446L;
            public void populateItem(Item item, String componentId, IModel rowModel) {
                String examId = ((ExamData) rowModel.getObject()).examId;
                String studentId = ((ExamData) rowModel.getObject()).studentId;
                Status status = ((ExamData) rowModel.getObject()).status;
                item.add(new ChangeExamStatusPanel(componentId, userId, examId, studentId, status));
            }
        });

        DefaultDataTable<ExamData, String> ddt = new DefaultDataTable<ExamData, String>("datatable", columns, exProv, 64);
        collapsible.add(ddt);
    } catch (NoSuchElementException e) {
        error(e.getMessage());
    }
}

collapsible是继承自父类(super class)(父类(super class)扩展Panel)的WebMarkupContainer(div标签)。 如您所见,在最后两列中,我不仅放入了简单的文本,还放入了一个特殊的面板。

ShowExamStatusPanel 包含一个标签,显示您是否已登录参加此考试:

class ShowExamStatusPanel extends Panel {
    private static final long serialVersionUID = 6359496765268390462L;

    public ShowExamStatusPanel(String id, final Status status) {
        super(id);
        this.setOutputMarkupId(true);
        Label showStatus = new Label("showStatus", new AbstractReadOnlyModel<String>() {
            private static final long serialVersionUID = 1L;

            public String getObject() {
                return ((status == Status.SIGNED_IN || status == Status.SIGNED_IN_CLOSED) ? (new ResourceModel("signed_in").getObject()) : (new ResourceModel("not_signed_in")).getObject());
            }
        });
        showStatus.add(new AttributeModifier("class", ((status == Status.SIGNED_IN || status == Status.SIGNED_IN_CLOSED) ? "examSignedUpColor" : "examNotSignedUpColor")));
        this.add(showStatus);
    }
}

ChangeExamStatusPanel 包含一个链接,可以切换您的考试状态(如果您不是,它会登录,否则会退出):

class ChangeExamStatusPanel extends Panel {
    private static final long serialVersionUID = -8527825882073976118L;

    public ChangeExamStatusPanel(final String id, final String userId, final String examId, final String studentId, final Status status) {
        super(id);
        this.setOutputMarkupId(true);
        MySystem mysystem = ((MySession) Session.get()).getMySystem();
        AjaxLink cesl= new AjaxLink("changeExamStatusLink") {
            private static final long serialVersionUID = 4306084754982648221L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                MySystem mysystem = ((MySession) Session.get()).getMySystem();
                try {
                    if (status == Status.SIGNED_IN) {
                        mysystem.exam(examId).removeParticipant(userId, studentId);
                    } else if (status == Status.NOT_SIGNED_IN) {
                        mysystem.exam(examId).addParticipant(userId, studentId);
                    }
                } catch (Exception e) {
                    NotFinishedExamsPanel.this.error(e.getMessage());
                }
                target.addChildren(NotFinishedExamsPanel.this, ChangeExamStatusPanel.class);
                target.addChildren(NotFinishedExamsPanel.this, ShowExamStatusPanel.class);
                target.add(NotFinishedExamsPanel.this);
            }
        };
        Label ceslText = new Label("linkText", ("[" + (new ResourceModel((status == Status.SIGNED_IN || status == Status.SIGNED_IN_CLOSED) ? "sign_off" : "sign_in")).getObject() + "]"));
        cesl.add(ceslText);
        ceslText.setVisibilityAllowed(status == Status.SIGNED_IN || status == Status.NOT_SIGNED_IN);
        this.add(cesl);         
    }
}

单击链接时,我希望刷新表格,因为一次考试的登录状态已更改。但我没有得到这个工作。使用上面的代码,当我点击链接时没有任何反应。如果我然后按 F5 并刷新整个页面,我会看到更改。

我需要做什么才能只刷新表格(包括内部面板)?

这里是 html 文件,如果你需要的话:

NotFinishedExamsPanel.html:

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<head>
</head>
<body>
    <wicket:extend>
        <table wicket:id="datatable" class="datatable" style="margin:0px"></table>
    </wicket:extend>
</body>
</html>

NotFinishedExamsPanel$ShowExamStatusPanel.html:

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<wicket:panel>
    <span wicket:id="showStatus"></span>
</wicket:panel>
</html>

NotFinishedExamsPanel$ChangeExamStatusPanel.html:

<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<wicket:panel>
    <a wicket:id="changeExamStatusLink" href="#"><span wicket:id="linkText"></span></a>
</wicket:panel>
</html>

ExamProvider.java:

class ExamProvider extends SortableDataProvider<ExamData, String> {
    private static final long serialVersionUID = 1476722834865141105L;
    private ExamDataProviderComparator comparator = new ExamDataProviderComparator();
    private List<ExamData> examList;

    public ExamProvider(List<ExamData> examList) {
        this.examList = examList;
        this.setSort("date", SortOrder.DESCENDING);
    }

    public Iterator<ExamData> iterator(long first, long count) {
        List<ExamData> newList = new ArrayList<ExamData>(this.examList);
        Collections.sort(newList, comparator);
        return newList.subList((int) first, (int) (first + count)).iterator();
    }

    public long size() {
        return this.examList.size();
    }

    public IModel<ExamData> model(final ExamData object) {
        return new AbstractReadOnlyModel<ExamData>() {
            private static final long serialVersionUID = -3048436145666499501L;

            public ExamData getObject() {
                return (ExamData) object;
            }
        };
    }

    class ExamDataProviderComparator implements Comparator<ExamData>, Serializable {
        private static final long serialVersionUID = 7660088204512731476L;

        public int compare(final ExamData o1, final ExamData o2) {
            PropertyModel<Comparable> model1 = new PropertyModel<Comparable>(o1, getSort().getProperty());
            PropertyModel<Comparable> model2 = new PropertyModel<Comparable>(o2, getSort().getProperty());

            int result = 0;
            if (model1.getObject() instanceof String && model2.getObject() instanceof String) {
                if (getSort().getProperty().equalsIgnoreCase("date")) {
                    try {
                        SimpleDateFormat sdt = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN);
                        Date d1 = sdt.parse(model1.getObject().toString());
                        Date d2 = sdt.parse(model2.getObject().toString());
                        result = d1.compareTo(d2);
                    } catch (ParseException e) {
                        result = Collator.getInstance(Locale.GERMAN).compare(model1.getObject(), model2.getObject());
                    }
                } else {
                    result = Collator.getInstance(Locale.GERMAN).compare(model1.getObject(), model2.getObject());
                }
            } else {
                result = model1.getObject().compareTo(model2.getObject());
            }
            if (!getSort().isAscending()) {
                result = -result;
            }

            return result;
        }

    }

}

最佳答案

仅当页面构造 时,Wicket 才会调用构造函数(页面或组件)。 所以在添加 NotFinishedExamsPanel 之后至 AjaxRequestTarget , Wicket 口 正在根据 ArrayList<ExamData> exams 中的数据刷新表(仍然是一样的)。

我建议您使用以下方法来实现 ExamProvider (我无法测试代码,因此仅将其作为建议):


    static class ExamProvider extends SortableDataProvider<ExamData, String> {

        private static final long serialVersionUID = 1L;

        private static final String DEFAULT_SORT = "foobar";

        private IModel<List<ExamData>> examsModel = new ExamDataLoader();

        @Override
        public Iterator<ExamData> iterator(long first, long count) {
            SortParam<String> sort = getSort();

            List<ExamData> examDataList = examsModel.getObject();

            // TODO sort
            String orderByColumn = sort != null ? DEFAULT_SORT : sort.getProperty();
            boolean desc = sort != null ? true : !sort.isAscending();

            return examDataList.iterator();
        }

        @Override
        public long size() {
            return examsModel.getObject().size();
        };

        @Override
        public IModel<ExamData> model(ExamData data) {
            final String examId = data.getExamId();
            return new LoadableDetachableModel<ExamData>() {
                @Override
                protected ExamData load() {
                    MySystem mysystem =  MySession.get().getMySystem();
                    final long userId = mysystem.account(userId).student().id();
                    Exam ex = mysystem.exam(examId);
                    return new ExamData(mysystem.account(userId).student().id(), examId);
                }
            };
        }

        @Override
        public void detach() {
            examsModel.detach();
            super.detach();
        }
    }

与:


    static class ExamDataLoader extends LoadableDetachableModel<List<ExamData>> {

        private static final long serialVersionUID = 1L;

        @Override
        protected List<ExamData> load() {
            MySystem mysystem =  MySession.get().getMySystem();
            long userId = mysystem.account(userId).student().id();

            List<String> examsIds = mysystem.exams();
            List<ExamData> exams = new ArrayList<>(examsIds.size());
                for (String exId : mysystem.exams()) {
                    Exam ex = mysystem.exam(exId);
                    if ((!(ex.hasResult(userId) && (ex.isPublished())))) {
                        exams.add(new ExamData(mysystem.account(userId).student().id(), exId));
                    }
                }
                return exams;
            }
        }

为了让你的生活更轻松一点,隐藏静态方法get()MySession与:


    public static MySession get() {
        return (MySession) Session.get();
    }

最后一件事:永远不要在构造函数中更改可见性(或组件的其他属性)(与初始问题的参数相同)。 所以代替:

 if (!mysystem.account(userId).isStudent()) { return; } 

覆盖onConfigure方法 根据给定的限制设置可见性。

关于java - 在 Wicket 口中正确刷新包含面板的表格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19377311/

相关文章:

java - Map putAll 覆盖还是添加?

java - 如何获取我的注释的参数作为 validator ?

html - -moz- -webkit- 等。用什么?

javascript - 如何使用左右按钮水平滚动 div

javascript - JQuery 移动对话框错误 SecurityError : The operation is insecure

PHP:即使有多个具有相同名称的复选框,也将提交的数据保留在表单中

java - Android线程在进程中间随机停止

java - Vaadin 7 - 更新文本区域的值已更改

html - @font-face 第一次访问该站点时不会加载,必须刷新/重新加载

java - eclipse 会阻止您使用特定的类吗?