Passing a variable to a function in a foreach loop

这一生的挚爱 提交于 2021-01-05 09:12:30

问题


I want to ask how variable in std:foreach is handled? I have this scenario that the same object is passed to a function regardless it it not the one that should be passed:

<std:foreach var="property" in="properties">
  <button onclick="unhide('collapse-primitive')"/>
  <span class="hidden" id="collapse-primitive">
    <ul class="">
      <li event:async-click="setItemPropertyType(property, 'String')">String</li>
      <li event:async-click="setItemPropertyType(property, 'Boolean')">Boolean</li>
      <li event:async-click="setItemPropertyType(property, 'Integer')">Integer</li>
      <li event:async-click="setItemPropertyType(property, 'Long')">Long</li>
      <li event:async-click="setItemPropertyType(property, 'Double')">Double</li>
      <li event:async-click="setItemPropertyType(property, 'Set')">Set</li>
      <li event:async-click="setItemPropertyType(property, 'List')">List</li>
      <li event:async-click="setItemPropertyType(property, 'Map')">Map</li>
    </ul>
  </span>
</std:foreach>

This code aboves generates a span for each item in the properties List, the problem is the function setItemPropertyType always gets the first item, whereas this is a loop so meaning the object passed for each setItemPropertyType method in the span should be different. Pardon if my explanation is not sufficient, but the code itself is quite self-explanatory.

The question now is, why the same object is passed to the method regardless user clicks a li in a different span?

I also suspect it is because of the id="collapse-primitive" here what is causing this weird behaviour. However, I do not know how to test it without and id because I don't know how to do this in Flavour, meaning how to inject the span in the code when the button in clicked, there is the id to just "hide" it or "show" it with CSS. And okay, this is another question.

So the summary of my questions are:

  1. Why std:foreach pass the same (first) variable in every function in a event:async-click
  2. How do you inject a span or any div element for that matter on button click even or what is the Flavour's way of doing this?

回答1:


The solution to this is to create something like a Dropdown component that it can render itself to the DOM through HTML wrapper.

In TeaVM this can be solved with:

public interface DropdownContent {
  void setDelegate(DropdownDelegate delegate);
}

This content can be anything HTML and expressed concretely as such:

@BindTemplate("templates/views/custom-dropdown-content.html")
public class CustomDropdownContent implements DropdownContent {
}

with this HTML template:

<span>
   <ul>
     <li>Item1</li>
     <li>Item2</li>
     <li>Item3</li>    
   </ul>
</span>

And obviously, other concrete implementation can be done with any HTML template.

Now, this is still just a content it must be shown to the DOM through some static method that can help build a component UI on-the-fly:

public void showDropdown(MouseEvent event) {
    HTMLElement element = (HTMLElement) event.getTarget();
    DropdownContent content = new CustomDropdownContent();
    Dropdown.show(content, element);
}

The HTML element here is optional if the rendering can be done anywhere in the DOM, if that's the case a typical DOM injection inside the Dropdown.show() method can be implemented:

document.getBody().appendChild(dropdownComponent.wrapper);
dropdownComponent.component = Templates.bind(dropdownComponent, dropdownComponent.wrapper);

This code above is not needed if you want to wrap the component from something that was clicked by the user, etc.

Now, for the the Dropdown itself, it can be implemented like this:

@BindElement(name = "dropdown")
@BindTemplate("templates/components/dropdown.html")
public class Dropdown {

  private static HTMLDocument document = HTMLDocument.current();
  private Fragment content;
  private Component component;
  private HTMLElement wrapper;

  public Dropdown(Fragment content) {
    this.content = content;
  }

  public Fragment getContent() {
    return content;
  }

  public void setContent(Fragment content) {
    this.content = content;
  }

  public static void show(DropdownContent content, HTMLElement wrapper) {
    Dropdown dropdown = new Dropdown(Templates.create(content));
    dropdown.wrapper = wrapper;
    dropdown.component = Templates.bind(dropdown, dropdown.wrapper);
  }
}

With a very simple HTML template:

<div>
  <std:insert fragment="content"/>
</div>

Finally, it can be used from a widget for example:

@BindElement(name = "simple-form")
@BindTemplate("templates/components/form.html")
public class FormComponent extends AbstractWidget {
    public void showDropdown(MouseEvent event) {
        HTMLElement element = (HTMLElement) event.getTarget();
        DropdownContent content = new CustomDropdownContent();
        Dropdown.show(content, element);
    }
}

form.html

<std:foreach var="property" in="properties">
  <button event:click="e -> showDropdown(e)"/>
</std:foreach>


来源:https://stackoverflow.com/questions/64812435/passing-a-variable-to-a-function-in-a-foreach-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!