Статьи

Динамическое связывание компонентов пользовательского интерфейса GWT

Вступление

Вероятно, все вы знаете главу в документации GWT о декларативном расположении с помощью UiBinder . В нем описан способ привязки отдельных компонентов панели к ее представлению пользовательского интерфейса, написанному на языке разметки, похожем на HTML. Это позволяет вам определить макет пользовательского интерфейса и скомпилировать его, так что вам не нужно делать это непосредственно в коде панели и иметь возможность переключать пользовательский интерфейс в любое время с другим.

Но что, если вам нужно переключить макет, когда приложение уже запущено?

В этот момент приходит связыватель Dynamic UI . Он позволяет указывать информацию о привязке в панели HTML и GWT так же, как в UiBinder GWT. Разница лишь в том, что вам не нужно иметь шаблон макета в это время. Вы можете загрузить его позже с помощью службы или динамически прочитать его / изменить его в коде.

Итак, давайте посмотрим, как вы это сделаете.

витрина


Для тех, кто нетерпелив:  вы можете найти демонстрацию этого в проекте acris-showcase-widgets .  

Предположим, мы собираемся создать простой калькулятор того, сколько кораблей имеет наш космический флот. Надо «вождям» отвечать за свои корабли. Таким образом, у нас будет два текстовых поля для ввода числа и кнопка для расчета всего:

<div class="dyn-panel">
        <div ui:field="message" class="dyn-message">Status messages are shown here</div>
        <div class="fleet-container">
                <div ui:field="description" class="dyn-description"></div>
                <input type="text" ui:field="ashtarShips" />
                <input type="text" ui:field="ptahShips" />
                <button ui:field="recalculateFleet">Recalculate fleet</button>
        </div>
</div>

Как вы можете видеть, мы будем выводить сообщения о состоянии / ошибках и иметь ссылку, указывающую на описание (вы можете удивиться, почему это тег «div», объяснение будет следовать).

Хорошо, давайте построим панель. Начнем с определения связующего:

public class DynamicallyBoundPanel extends Composite {
        interface DynamicallyBoundPanelUiBinder extends DynamicUiBinder<Widget, DynamicallyBoundPanel> {}

        private static final DynamicallyBoundPanelUiBinder binder = GWT.create(DynamicallyBoundPanelUiBinder.class);

        ...
}

Как видите, синтаксис аналогичен синтаксису GWT, вместо UiBinder мы используем DynamicUiBinder .   

И поля будут следовать:

        @UiField
        protected Label message;

        // this is acris-widget Hyperlink because GWT's misses wrap method!
        @UiField
        protected Hyperlink description;

        @UiField
        protected TextBox ashtarShips;

        @UiField
        protected TextBox ptahShips;

        @UiField
        protected Button recalculateFleet;

Хм, теперь единственное, чего не хватает, это клей между шаблоном и переплетом:

        public DynamicallyBoundPanel() {
                // load the template e.g. from service ...
                String htmlTemplate = "<div class=\"dyn-panel\"><div ui:field=\"message\" class=\"dyn-message\">Status messages are shown here</div><div class=\"fleet-container\"><div ui:field=\"description\" class=\"dyn-description\"></div><input type=\"text\" ui:field=\"ashtarShips\" /><input type=\"text\" ui:field=\"ptahShips\" /><button ui:field=\"recalculateFleet\">Recalculate fleet</button</div></div>";
                binder.setViewTemplate(htmlTemplate);

                // known from GWT UiBinder - initialize
                initWidget(binder.createAndBindUi(this));
        
                ...
        }

В целях пояснения шаблон HTML непосредственно помещается в переменную «htmlTemplate». Обычно вы будете читать его из сервиса.

Каждый тег, который должен быть сопоставлен с виджетом поля на панели, должен иметь соответствующее имя в атрибуте ui: field . Значение совпадает с именем поля. 

Основное отличие между GWT UiBinder и DynamicUiBinder заключается в настройке шаблона. Прежде чем выполнить binder.createAndBindUi (this) , связыватель должен иметь его. Вы можете рассматривать связыватель как фабрику панелей, поэтому последовательные вызовы пары методов setViewTemplate / createAndBindUi могут привести к разным результатам (если шаблон изменяется). Таким образом, вы можете сохранить одну такую ​​фабрику связывателя инициализированной и предоставить только шаблон, основанный на требованиях логики бизнеса.  

С помощью связанных полей вы можете выполнить обычное кодирование GWT, например, установив значение сообщения:

        message.setText("You accessed " + event.getValue() + ". Thank you for your interest in AcrIS. For more information, please visit http://acris.googlecode.com");

 

И это все для витрины … не стесняйтесь проверить это на страницах AcrIS .