Beispiel #1
0
  public void render(final Listitem item, final Object data, final int index) throws Exception {
    final Listbox listbox = (Listbox) item.getParent();
    final int size = listbox.getModel().getSize();
    // B70-ZK-2555: in order to handle dynamic template name
    final String subtype =
        item instanceof Listgroup ? "group" : item instanceof Listgroupfoot ? "groupfoot" : null;
    final Template tm = resolveTemplate(listbox, item, data, index, size, "model", subtype);
    if (tm == null) {
      item.setLabel(Objects.toString(data));
      item.setValue(data);
    } else {
      final ForEachStatus iterStatus =
          new AbstractForEachStatus() { // provide iteration status in this context
            private static final long serialVersionUID = 1L;

            public int getIndex() {
              return index;
            }

            public Object getCurrent() {
              return data;
            }

            public Integer getEnd() {
              return size;
            }
          };

      final String var = (String) tm.getParameters().get(EACH_ATTR);
      final String varnm = var == null ? EACH_VAR : var; // var is not specified, default to "each"
      final String itervar = (String) tm.getParameters().get(STATUS_ATTR);
      final String itervarnm =
          itervar == null
              ? (var == null ? EACH_STATUS_VAR : varnm + STATUS_POST_VAR)
              : itervar; // provide default value if not specified

      // bug 1188, EL when nested var and itervar
      Object oldVar = listbox.getAttribute(varnm);
      Object oldIter = listbox.getAttribute(itervarnm);
      listbox.setAttribute(varnm, data);
      listbox.setAttribute(itervarnm, iterStatus);

      final Component[] items = filterOutShadows(listbox, tm.create(listbox, item, null, null));

      // Bug ZK-2789: do not use setAttribute when actually trying to removeAttribute
      if (oldVar != null) {
        listbox.setAttribute(varnm, oldVar);
      } else {
        listbox.removeAttribute(varnm);
      }
      if (oldIter != null) {
        listbox.setAttribute(itervarnm, oldIter);
      } else {
        listbox.removeAttribute(itervarnm);
      }

      if (items.length != 1)
        throw new UiException("The model template must have exactly one item, not " + items.length);

      final Listitem nli = (Listitem) items[0];
      nli.setAttribute(BinderCtrl.VAR, varnm); // for the converter to get the value

      // ZK-2552
      recordRenderedIndex(listbox, items.length);
      nli.setAttribute(AbstractRenderer.IS_TEMPLATE_MODEL_ENABLED_ATTR, true);

      nli.setAttribute(
          AbstractRenderer.CURRENT_INDEX_RESOLVER_ATTR,
          new IndirectBinding() {
            public Binder getBinder() {
              return BinderUtil.getBinder(nli, true);
            }

            @SuppressWarnings("unchecked")
            public void setValue(BindELContext ctx, Object value) {
              int idx = BindListitemRenderer.this.getRenderedIndex(listbox, nli.getIndex());
              ListModel<?> listmodel = listbox.getListModel();
              if (idx >= 0 && idx < listmodel.getSize()) {
                if (listmodel instanceof ListModelArray) {
                  ((ListModelArray<Object>) listmodel).set(idx, value);
                } else if (listmodel instanceof ListModelList<?>) {
                  ((ListModelList<Object>) listmodel).set(idx, value);
                }
              } else {
                // out of range, should ignore to compatible with old version(when we didn't
                // implement save) or throw exception?
              }
            }

            public Component getComponent() {
              return nli;
            }

            public Object getValue(BindELContext ctx) {
              return listbox
                  .getModel()
                  .getElementAt(
                      BindListitemRenderer.this.getRenderedIndex(listbox, nli.getIndex()));
            }
          });
      addItemReference(
          listbox, nli, index, varnm); // kept the reference to the data, before ON_BIND_INIT

      nli.setAttribute(itervarnm, iterStatus);

      // sync open state
      if (nli instanceof Listgroup && item instanceof Listgroup) {
        ((Listgroup) nli).setOpen(((Listgroup) item).isOpen());
      }

      // ZK-1787 When the viewModel tell binder to reload a list, the other component that bind a
      // bean in the list will reload again
      // move TEMPLATE_OBJECT (was set in resoloveTemplate) to current for check in
      // addTemplateTracking
      Object obj = item.removeAttribute(TemplateResolver.TEMPLATE_OBJECT);
      // Bug ZK-2789: do not use setAttribute when actually trying to removeAttribute
      if (obj != null) {
        nli.setAttribute(TemplateResolver.TEMPLATE_OBJECT, obj);
      } else {
        nli.removeAttribute(TemplateResolver.TEMPLATE_OBJECT);
      }

      // add template dependency
      addTemplateTracking(listbox, nli, data, index, size);

      if (nli.getValue() == null) // template might set it
      nli.setValue(data);
      item.setAttribute(Attributes.MODEL_RENDERAS, nli);
      // indicate a new item is created to replace the existent one
      item.detach();
    }
  }
  public void render(final Comboitem item, final Object data, final int index) throws Exception {
    final Combobox cb = (Combobox) item.getParent();
    final ListModel<?> model = cb.getModel();
    final int size = model.getSize();
    final Template tm = resoloveTemplate(cb, item, data, index, size, "model");
    if (tm == null) {
      item.setLabel(Objects.toString(data));
      item.setValue(data);
    } else {
      final ForEachStatus iterStatus =
          new AbstractForEachStatus() { // provide iteration status in this context
            private static final long serialVersionUID = 1L;

            public int getIndex() {
              return index;
            }

            public Object getEach() {
              return data;
            }

            public Integer getEnd() {
              return size;
            }
          };

      final String var = (String) tm.getParameters().get(EACH_ATTR);
      final String varnm = var == null ? EACH_VAR : var; // var is not specified, default to "each"
      final String itervar = (String) tm.getParameters().get(STATUS_ATTR);
      final String itervarnm =
          itervar == null
              ? (var == null ? EACH_STATUS_VAR : varnm + STATUS_POST_VAR)
              : itervar; // provide default value if not specified

      // bug 1188, EL when nested var and itervar
      Object oldVar = cb.getAttribute(varnm);
      Object oldIter = cb.getAttribute(itervarnm);
      cb.setAttribute(varnm, data);
      cb.setAttribute(itervarnm, iterStatus);

      final Component[] items = tm.create(cb, item, null, null);

      cb.setAttribute(varnm, oldVar);
      cb.setAttribute(itervarnm, oldIter);

      if (items.length != 1)
        throw new UiException("The model template must have exactly one item, not " + items.length);

      final Comboitem nci = (Comboitem) items[0];
      nci.setAttribute(BinderImpl.VAR, varnm); // for the converter to get the value

      if (model instanceof ListSubModel) {
        // ZK-992 wrong item when binding to combbox with submodel implementation
        // combobox has a internal model as the submodel,
        // I don't have way to access the submodel, and user doesn't has info to notify model[index]
        // changed.
        // so I set the value directly.
        nci.setAttribute(varnm, data);
      } else {
        addItemReference(
            cb, nci, index, varnm); // kept the reference to the data, before ON_BIND_INIT
      }

      nci.setAttribute(itervarnm, iterStatus);

      // add template dependency
      addTemplateTracking(cb, nci, data, index, size);

      if (nci.getValue() == null) // template might set it
      nci.setValue(data);
      item.setAttribute("org.zkoss.zul.model.renderAs", nci);
      // indicate a new item is created to replace the existent one
      item.detach();

      // bug #ZK-677: combobox selection is lost after reload model
      // binding Comboitem immediately, @see BindUiLifeCycle#afterComponentAttached
      Events.sendEvent(new Event(BinderImpl.ON_BIND_INIT, nci));
    }
  }