Pregunta

I am trying to create a web-page where some elements (forms and buttons) become visible or are being hidden when some other elements (buttons) are clicked.
I try to find a way to manage this, that is re-usable, and easy to maintain.

My current solution is shown below, but I hope someone has a more elegant solution.
The problem with my own solution is that it will become difficult to read when the number of dependencies increase. It will then also require a lot of editing when I add another button and form.


My current solution is to use an observable to manage the state of the forms, like this:

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>

Dart:

  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';
      });

    });
  }
¿Fue útil?

Solución 3

You could use polymer's template functionality like

<template if="showA">...

This should work without embedding your elements within Polymer elements too.
This discussion provides some information how to use <template> without Polymer elements. Using Polymer elements could also be useful.
It all depends on your requirements/preferences.

Angular.dart is also useful for such view manipulation.

If you want to use plain Dart/HMTL I don't have ideas how to simplify your code.

Otros consejos

You can use basic CSS to show/hide the elements.

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;
}

In Dart just get the data-group (or whatever you want to call this) attribute from the button. Toggle the CSS classes (show-buttons, show-a and show-b) on the container element to switch between the buttons and the specific forms.

This solution is very easy to extend on.

You can use something like this to handle all the elements in a generic way :

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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top