Как управлять зависимостями элементов DOM

Я пытаюсь создать веб-страницу, на которой некоторые элементы (формы и кнопки) становятся видимыми или скрываются при нажатии на некоторые другие элементы (кнопки).
Я пытаюсь найти способ управлять этим, т.е. удобен в использовании и прост в обслуживании.

Мое текущее решение показано ниже, но я надеюсь, что у кого-то есть более элегантное решение.
Проблема с моим собственным решением заключается в том, что его становится трудно читать, когда количество зависимостей увеличивается. Это также потребует много редактирования, когда я добавлю еще одну кнопку и форму.


Мое текущее решение состоит в том, чтобы использовать наблюдаемое для управления состоянием форм, например:

HTML:

  <button id="button-A">Show form A, hide button A and B</button>
  <button id="button-B">Show form B, hide button A and B</button>
  <form id="form-A">
    ...this form is initially hidden
    ...some form elements
    <button id="cancel-A">Hide form A, show button A and B</button>
  </form>
  <form id="form-B">
    ...this form is initially hidden
    ...some form elements
    <button id="cancel-B">Hide form B, show button A and B</button>
  </form>

Дарт:

  import 'dart:html';
  import 'package:observe/observe.dart';

  final $ = querySelector;
  final $$ = querySelectorAll;

  Map<String, bool> toBeObserved = {
    "showFormA" : false,
    "showFormB" : false
  };

  // make an observable map
  ObservableMap observeThis = toObservable(toBeObserved);

  // start managing dependencies
  main() {
    // add click event to buttons
    $('#button-A')
    ..onClick.listen((E) => observeThis["showFormA"] = true);
    $('#button-B')
    ..onClick.listen((E) => observeThis["showFormB"] = true);

    // add click events to form buttons
    $('#cancel-A')
    ..onClick.listen((E) {
      E.preventDefault();
      E.stopPropagation();
      observeThis["showFormA"] = false;
    });
    $('#cancel-B')
    ..onClick.listen((E) {
      E.preventDefault();
      E.stopPropagation();
      observeThis["showFormB"] = false;
    });

    // listen for changes
    observeThis.changes.listen((L) {

      L.where((E) => E.key == 'showFormA').forEach((R) {
        $('#form-A').style.display = (R.newValue) ? 'block' : 'none';
        $('#button-A').style.display = (R.newValue || observeThis['showFormB']) ? 'none' : 'inline-block';
        $('#button-B').style.display = (R.newValue || observeThis['showFormB']) ? 'none' : 'inline-block';
      });
      L.where((E) => E.key == 'showFormB').forEach((R) {
        $('#form-B').style.display = (R.newValue) ? 'block' : 'none';
        $('#button-A').style.display = (R.newValue || observeThis['showFormA']) ? 'none' : 'inline-block';
        $('#button-B').style.display = (R.newValue || observeThis['showFormA']) ? 'none' : 'inline-block';
      });

    });
  }

person Hendrik Jan    schedule 06.01.2014    source источник


Ответы (3)


Вы можете использовать функциональность шаблона полимера, например

<template if="showA">...

Это должно работать и без встраивания ваших элементов в элементы Polymer.
Это обсуждение содержит некоторую информацию о том, как использовать <template> без элементов Polymer. Использование полимерных элементов также может быть полезным.
Все зависит от ваших требований/предпочтений.

Angular.dart также полезен для таких манипуляций с представлениями.

Если вы хотите использовать простой Dart/HMTL, у меня нет идей, как упростить ваш код.

person Günter Zöchbauer    schedule 06.01.2014
comment
Здравствуйте, Гюнтер, спасибо за это предложение. Пока это кажется мне самым универсальным решением. Я рассмотрю полимер в будущем, когда у меня останется немного времени. - person Hendrik Jan; 06.01.2014

Вы можете использовать базовый CSS для отображения/скрытия элементов.

HTML

<div id="container" class="show-buttons">
    <button id="button-A" class="btn" data-group="a">...</button>
    <button id="button-B" class="btn" data-group="b">...</button>
    <form id="form-A" class="form group-a">...</button>
    <form id="form-B" class="form group-b">...</button>
</div>

CSS

.btn, .form {
  display: none;
}

.show-buttons .btn,
.show-a .form.group-a,
.show-b .form.group-b {
  display: block;
}

В Dart просто получите атрибут data-group (или как вы хотите это назвать) с кнопки. Переключите классы CSS (show-buttons, show-a и show-b) в элементе container, чтобы переключаться между кнопками и конкретными формами.

Это решение очень легко расширить.

person Tom Verelst    schedule 06.01.2014

Вы можете использовать что-то вроде этого для обработки всех элементов общим способом:

final Iterable<ButtonElement> buttons = querySelectorAll('button')
    .where((ButtonElement b) => b.id.startsWith('button-'));

final Iterable<ButtonElement> cancels = querySelectorAll('button')
    .where((ButtonElement b) => b.id.startsWith('cancel-'));

final Iterable<FormElement> forms = querySelectorAll('form')
    .where((FormElement b) => b.id.startsWith('form-'));

buttons.forEach((b) {
  b.onClick.listen((e) {
    // name of clicked button
    final name = b.id.substring(b.id.indexOf('-') + 1);
    // hide all buttons
    buttons.forEach((b) => b.hidden = true)
    // show the good form
    querySelector('#form-$name').hidden = false;
  });
});

cancels.forEach((b) {
  b.onClick.listen((e) {
    // show all buttons
    buttons.forEach((b) => b.hidden = false);
    // hide all forms
    forms.forEach((b) => b.hidden = true);
    // prevent default
    e.preventDefault();
  });
});

// hide all form at startup
forms.forEach((f) => f.hidden = true);
person Alexandre Ardhuin    schedule 06.01.2014
comment
Привет Александр, это красивый код. Это будет работать, пока я просто добавляю формы и кнопки для отображения этих форм. Я надеюсь найти какое-то универсальное решение в будущем, которое также будет работать при изменении логики (например, показывать/скрывать несколько форм, показывать/скрывать поля в формах в зависимости от видимости других форм). - person Hendrik Jan; 06.01.2014