添加应用程序逻辑。

到目前为止,我们已经使用 UiBindersElements 设计了我们的 UI。

在本节中,我们将学习如何向我们的 UI 添加逻辑。我们将接触到非常基本的数据建模以及如何处理原生元素事件。

  1. 通过将以下标记添加到 Main.ui.xml 文件中来创建 *添加项目对话框*。

    <g:HTMLPanel>
      ...
      <paper-dialog ui:field="addItemDialog"
                    entry-animation="fade-in-animation"
                    class="dialog" modal="">
        <h2>Add Item</h2>
        <paper-input ui:field="titleInput" label="Title" required=""
                     auto-validate="" error-message="required input!"/>
        <div class="textarea-container iron-autogrow-textarea">
            <paper-textarea ui:field="descriptionInput" label="Notes"/>
        </div>
        <div class="buttons">
            <paper-button dialog-dismiss="">Cancel</paper-button>
            <paper-button ui:field="confirmAddButton"
                          dialog-confirm="">OK</paper-button>
        </div>
      </paper-dialog>
    </g:HTMLPanel>
    

    提示:可以使用属性快速定义某些聚合物操作,例如 entry-animation='fade-in-animation'

    注意:不要忘记在 Main.java 类中导入所有新的元素。

  2. Main.ui.xml 文件中定义的所有字段添加到 Main.java 类中。

    @UiField PaperDrawerPanelElement drawerPanel;
    @UiField HTMLElement content;
    
    @UiField PaperFabElement addButton;
    @UiField PaperDialogElement addItemDialog;
    @UiField PaperInputElement titleInput;
    @UiField PaperTextareaElement descriptionInput;
    @UiField PaperButtonElement confirmAddButton;
    
  3. Main 构造函数中为浮动操作按钮添加一个点击处理程序。

    public Main() {
      initWidget(ourUiBinder.createAndBindUi(this));
    
      addButton.addEventListener("click", new EventListener() {
        @Override
        public void handleEvent(Event event) {
            addItemDialog.open();
        }
      });
    }
    

    注意:由于元素缺乏用于处理 GWT 事件的方法,因此我们不能使用 @UiHandler 注解。因此,我们必须在构造函数中配置事件。

  4. 重新加载应用程序

    现在,你可以通过点击右下角的浮动操作按钮来打开对话框。

  5. 为显示项目创建一个 UiBinder 小部件:Item.ui.xmlItem.java

    • Item.ui.xml
        <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
                     xmlns:g='urn:import:com.google.gwt.user.client.ui'
                     xmlns:p='urn:import:com.vaadin.polymer.paper.widget'>
    
          <div class="item vertical center-justified layout">
            <style>
              .title {
                padding-left: 20px;
                font-size: 150%;
                font-weight: normal;
              }
              .done {
                text-decoration: line-through;
              }
              .paper-checkbox {
                top: -2px;
              }
            </style>
            <div class="vertical-section">
              <h4>
                <paper-checkbox ui:field="done"/>
                <span ui:field="title" class='title'>Go to Google</span>
              </h4>
              <div ui:field="description"/>
            </div>
          </div>
        </ui:UiBinder>
    
    • Item.java:为了简单起见,我们将使用此类作为项目 POJO。
        package org.gwtproject.tutorial.client;
    
        import com.google.gwt.core.shared.GWT;
        import com.google.gwt.dom.client.DivElement;
        import com.google.gwt.dom.client.Element;
        import com.google.gwt.uibinder.client.UiBinder;
        import com.google.gwt.uibinder.client.UiField;
        import com.vaadin.polymer.elemental.Event;
        import com.vaadin.polymer.elemental.EventListener;
        import com.vaadin.polymer.paper.element.PaperCheckboxElement;
    
        public class Item {
    
          private final DivElement element;
    
          interface ItemUiBinder extends UiBinder<DivElement, Item> {
          }
    
          private static ItemUiBinder ourUiBinder = GWT.create(ItemUiBinder.class);
    
          @UiField Element title;
          @UiField Element description;
          @UiField PaperCheckboxElement done;
    
          public Item() {
            element = ourUiBinder.createAndBindUi(this);
    
            done.addEventListener("iron-change", new EventListener() {
              @Override
              public void handleEvent(Event event) {
                if (done.getActive()) {
                  title.addClassName("done");
                } else {
                  title.removeClassName("done");
                }
              }
            });
          }
    
          public String getTitle() {
            return title.getInnerText();
          }
          public void setTitle(String s) {
            title.setInnerText(s);
          }
          public String getDescription() {
            return description.getInnerText();
          }
          public void setDescription(String s) {
            description.setInnerText(s);
          }
          public boolean isDone() {
            return done.getActive();
          }
          public void setDone(boolean b) {
            done.setActive(b);
          }
          public DivElement getElement() {
            return element;
          }
        }
    
  6. 添加在点击保存按钮时创建项目的逻辑。

      ...
      private List<Item> items = new ArrayList<>();
    
      public Main() {
        ...
        addButton.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            addItemDialog.open();
          }
        });
    
        confirmAddButton.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            if (!titleInput.getValue().isEmpty()) {
              addItem(titleInput.getValue(), descriptionInput.getValue());
              // clear text fields
              titleInput.setValue("");
              descriptionInput.setValue("");
            }
          }
        });
      }
    
      private void addItem(String title, String description) {
        Item item = new Item();
        item.setTitle(title);
        item.setDescription(description);
        content.appendChild(item.getElement());
        items.add(item);
      }
      ...
    
  7. 重新加载应用程序

    现在,你可以添加待办事项并使用复选框将其标记为已完成。

  8. 在构造函数中添加 *清除全部* 和 *清除已完成* 菜单项处理程序。

      public Main() {
        ...
        menuClearAll.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            closeMenu();
            // remove all child elements
            while (content.hasChildNodes()) {
              content.removeChild(content.getFirstChild());
            }
          }
        });
    
        menuClearDone.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            closeMenu();
    
            for (Item item : items) {
              if (item.isDone()) {
                content.removeChild(item.getElement());
                items.remove(item);
              }
            }
          }
        });
      }
    
      private void closeMenu() {
        if (drawerPanel.getNarrow()) {
          drawerPanel.closeDrawer();
        }
      }
    

    注意:closeMenu() 方法仅在应用程序在移动设备上查看或浏览器窗口窄到侧边菜单折叠时才有用。因此,我们使用此方法在点击任何菜单项后隐藏菜单。

  9. 最终的 Main.java 应如下所示

    package org.gwtproject.tutorial.client;
    
    import com.google.gwt.core.client.GWT;
    import com.google.gwt.uibinder.client.UiBinder;
    import com.google.gwt.uibinder.client.UiField;
    import com.google.gwt.user.client.ui.Composite;
    import com.google.gwt.user.client.ui.HTMLPanel;
    import com.vaadin.polymer.elemental.*;
    import com.vaadin.polymer.paper.element.*;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Main extends Composite {
      interface MainUiBinder extends UiBinder<HTMLPanel, Main> {
      }
    
      private static MainUiBinder ourUiBinder = GWT.create(MainUiBinder.class);
    
      @UiField PaperDrawerPanelElement drawerPanel;
    
      @UiField PaperIconItemElement menuClearAll;
      @UiField PaperIconItemElement menuClearDone;
    
      @UiField HTMLElement content;
      @UiField PaperFabElement addButton;
    
      @UiField PaperDialogElement addItemDialog;
      @UiField PaperInputElement titleInput;
      @UiField PaperTextareaElement descriptionInput;
      @UiField PaperButtonElement confirmAddButton;
    
      private List<Item> items = new ArrayList<>();
    
      public Main() {
        initWidget(ourUiBinder.createAndBindUi(this));
    
        addButton.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            addItemDialog.open();
          }
        });
    
        confirmAddButton.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            if (!titleInput.getValue().isEmpty()) {
              addItem(titleInput.getValue(), descriptionInput.getValue());
              // clear text fields
              titleInput.setValue("");
              descriptionInput.setValue("");
            }
          }
        });
    
        menuClearAll.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            closeMenu();
            // remove all child elements
            while (content.hasChildNodes()) {
              content.removeChild(content.getFirstChild());
            }
          }
        });
    
        menuClearDone.addEventListener("click", new EventListener() {
          public void handleEvent(Event event) {
            closeMenu();
    
            for (Item item : items) {
              if (item.isDone()) {
                content.removeChild(item.getElement());
                items.remove(item);
              }
            }
          }
        });
      }
    
      private void addItem(String title, String description) {
        Item item = new Item();
        item.setTitle(title);
        item.setDescription(description);
        content.appendChild(item.getElement());
        items.add(item);
      }
    
      private void closeMenu() {
        if (drawerPanel.getNarrow()) {
          drawerPanel.closeDrawer();
        }
      }
    }
    
  10. 你的 TodoList.java 应如下所示

    package org.gwtproject.tutorial.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.user.client.ui.RootPanel;
    import com.vaadin.polymer.Polymer;
    import com.vaadin.polymer.elemental.Function;
    import com.vaadin.polymer.iron.element.IronIconElement;
    import com.vaadin.polymer.paper.element.*;
    
    import java.util.Arrays;
    
    public class TodoList implements EntryPoint {
    
        public void onModuleLoad() {
            Polymer.importHref(Arrays.asList(
                    "iron-icons/iron-icons.html",
                    PaperIconItemElement.SRC,
                    PaperRippleElement.SRC,
                    IronIconElement.SRC,
                    PaperDrawerPanelElement.SRC,
                    PaperHeaderPanelElement.SRC,
                    PaperToolbarElement.SRC,
                    PaperFabElement.SRC,
                    PaperDialogElement.SRC,
                    PaperTextareaElement.SRC,
                    PaperInputElement.SRC,
                    PaperButtonElement.SRC,
                    PaperCheckboxElement.SRC
            ), new Function() {
                public Object call(Object arg) {
                    startApplication();
                    return null;
                }
            });
    
        }
    
        private void startApplication() {
            RootPanel.get().add(new Main());
        }
    
  11. 重新加载应用程序

    • 添加几个项目
    • 将其中一些标记为已完成
    • 点击 *清除已完成* 菜单项
    • 点击 *清除全部* 菜单项

总结

在本章中,我们学习了如何

  1. 将更多基于元素的 UiBinder 小部件添加到我们的应用程序中。
  2. 为元素添加事件处理程序。
  3. 使用美观且基于聚合物的组件,如纸质对话框和按钮。
  4. 在 GWT 中处理非常基本的数据模型。

免责声明