将组件实例从 MainView 传递到单独的 java 类文件中的选项卡内容组件

问题描述 投票:0回答:1

我试图将两个

SvgIcon
MainView
传递到单独的Java类文件,它们是选项卡内容,所以我可以更改图标,但我找不到实现这样的功能的元素:

public SvgIcon getSvgIcon(String classSvgIcon) {
    return (SvgIcon) CurrentInstance.get(SvgIcon.class).findAncestor(SvgIcon.class).hasClassName(classSvgIcon);
} 

因为我认为它应该返回与元素中包含的类名相对应的

SvgIcon
元素,即使我更喜欢 ID,但我看到没有
hasIdAttribute()
函数,但它不起作用。 .

然后我尝试传递 MainView UI 类来直接访问我想要更改的组件,如下所示:

public static MainView getCurrent() {
    return (MainView) CurrentInstance.get(UI.class);
}

但是即使在选项卡内容类中我现在可以调用

MainView.getCurrent().myIconElement
但是在函数中它说
Cannot cast from UI to MainView
...应该如何正确重写该函数以便我可以访问我想要更改的svg图标?

提前感谢大家! 干杯!

[编辑]

我正在尝试实现更改图标的示例...

/* ************************************************************ 
 *                                                            *
 *          MainView class                                    *
 *                                                            *
 ************************************************************ */
package com.myexample.application.views.main;

import java.util.HashMap;
import java.util.Map;

import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.NativeLabel;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.SvgIcon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.component.tabs.TabsVariant;
import com.vaadin.flow.internal.CurrentInstance;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.HighlightConditions;

import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouterLayout;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.flow.server.StreamResource;

@PageTitle("Main")
@Route("")
public class MainView extends VerticalLayout implements RouterLayout, BeforeEnterObserver {

    private Map<Tab, RouterLink> tabSheets = new HashMap<>();
    private Tabs mainTabs; 

    private HorizontalLayout toolbar;       
    private NativeLabel appname;
    public SvgIcon iconToChange;

    public MainView() {
        
        RouteTabs tabsToAdd = new RouteTabs();
        tabsToAdd.addTab(new RouterLink("Tab 1", MyTab1.class), VaadinIcon.EYE.create());
        tabsToAdd.addTab(new RouterLink("Tab 2", MyTab2.class), VaadinIcon.EYE.create());
        
        add(getToolbar(), tabsToAdd);               
    }
    
    @Override
    public void beforeEnter(BeforeEnterEvent event) {
        if (event.getNavigationTarget() == MainView.class) {
            event.forwardTo(MyTab1.class);
        }       
    }    

    public static MainView getCurrent() {
        return (MainView) CurrentInstance.get(UI.class).getCurrent();       
        //return CurrentInstance.get(UI.class);
        //return UI.getCurrent();
    }    
    
    public SvgIcon getIconToChange() { return (SvgIcon) iconToChange; }
    
    private HorizontalLayout getToolbar() {                     
        
        HorizontalLayout leftLayout = new HorizontalLayout();
        
        appname = new NativeLabel("My Test");
        appname.setClassName("title-style");
        
        leftLayout.add(appname);
        leftLayout.setAlignItems(FlexComponent.Alignment.START);
        leftLayout.setWidth("100%");
                
        HorizontalLayout rightLayout = new HorizontalLayout();
        
        StreamResource svgIconResource = new StreamResource("myOff_Icon.svg",
                () -> getClass().getResourceAsStream("/img/myOff_Icon.svg"));
        svgIconResource.setCacheTime(0);        
        iconToChange = new SvgIcon(svgIconResource);
        iconToChange.addClassName("iconToChange");
        iconToChange.setId("iconToChange");
        iconToChange.setTooltipText("IconToChange");
        
        rightLayout.add(iconToChange);
        rightLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
        rightLayout.setWidth("100%");

        var toolbar = new HorizontalLayout(leftLayout, rightLayout);
        toolbar.setWidthFull();
        toolbar.addClassName("toolbar");      
                
        return toolbar;
    }    
    
    
    private static class RouteTabs extends Tabs implements BeforeEnterObserver {
        private final Map<RouterLink, Tab> routerLinkTabMap = new HashMap<>();
        
        public void addTab(RouterLink routerLink, Icon iconToAdd) {
            routerLink.setHighlightCondition(HighlightConditions.sameLocation());
            routerLink.setHighlightAction(
                (link, shouldHighlight) -> {
                    if (shouldHighlight) setSelectedTab(routerLinkTabMap.get(routerLink));
                }             
            );            
            routerLinkTabMap.put(routerLink, new Tab(iconToAdd, routerLink));
            add(routerLinkTabMap.get(routerLink));
            this.addThemeVariants(TabsVariant.LUMO_EQUAL_WIDTH_TABS);
            this.setMaxWidth("100%");
            this.setWidthFull();
        }

        @Override
        public void beforeEnter(BeforeEnterEvent event) {
            // In case no tabs will match
            setSelectedTab(null);
        }
    }
    
    /*public SvgIcon getSvgIcon(String idSvgIcon) {
        //return (SvgIcon) CurrentInstance.get(SvgIcon.class).equals(getElement().getAttribute("id").equals(idSvgIcon));
        //return (SvgIcon) CurrentInstance.get(SvgIcon.class).findAncestor(SvgIcon.class).hasClassName(idSvgIcon);
        return (SvgIcon) CurrentInstance.get(SvgIcon.class).getElement().hasAttribute("id");
    } */
    
}

/* ************************************************************ 
 *                                                            *
 *          MainView class                                    *
 *                                                            *
 ************************************************************ */
 
 
/* ************************************************************ 
 *                                                            *
 *          MyTab1.class class                                *
 *                                                            *
 ************************************************************ */
 
 package com.myexample.application.views.main;

import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.icon.SvgIcon;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.StreamResource;

@Route(value="mytab1", layout = MainView.class)
public class MyTab1 extends VerticalLayout {
    
    /**
     * 
     */
    private SvgIcon iconChangeTo;
    private Text localText;
    private Button localButton;
        
    public ARDevices() {                    
        localText = new Text("My Tab 1");
            
        localButton = new Button("Change Icon");
        localButton.addClickListener(e -> {
            //iconChangeTo = Element.getAttribute("id").
            //iconChangeTo = UI.getCurrent().navigate(SvgIcon.class).ifPresent(icon -> icon.hasClassName("iconToChange")).      
            
            //SvgIcon icon = ((MainView) MainView.getCurrent()).getIconToChange();
            //MainView.getCurrent()

            SvgIcon icon = MainView.getCurrent().getIconToChange()
            
            
            //UIclass.iconToChange.setSrc( new StreamResource("myON_Icon.svg",
            //  () -> getClass().getResourceAsStream("/img/myON_Icon.svg")) );
        });
                
        add(localText, localButton);
    }   
}
/* ************************************************************ 
 *                                                            *
 *          MyTab1.class class                                *
 *                                                            *
 ************************************************************ */
vaadin vaadin-flow
1个回答
0
投票

我知道可以通过三种方法从子视图获取 MainView 实例。

第一个选项是获取当前 UI 实例并在其子级中找到 childView:

MainView mainView = (MainView) UI.getCurrent().getChildren()
            .filter(component -> component.getClass() == MainView .class).findFirst().orElse(null);


第二个选项类似,但反之亦然,您从子视图开始向上看。它看起来更丑陋,因为你一次只能获取 1 个父级,而 getChildren 返回一个可过滤的流:

MainView mainView = null;
Optional<Component> parentOpt = this.getParent();
while(parentOpt.isPresent()) {
    Component parent = parentOpt.get();
    if(parent instanceof MainView) {
        mainView = (MainView) parent;
        parentOpt = Optional.empty(); // stop the loop
    } else {
        // look further
        parentOpt = parent.getParent();
    }
}

最后是第三个选项,这就是我使用的,但它需要依赖注入。在 MainView 以及所有可能需要它的子视图中,我们注入一个

MainViewBus
(不太确定命名。如果可以的话,为它找到一个更好的名称),我们可以使用它直接获取 MainView 。这里不需要 HTML 元素子/父爬行。

@Component
@UIScope
public class MainViewBus {
    private MainView mainView;

    public MainViewBus() {
    }

    public MainView getMainView() {
        return this.mainView;
    }
    public void setMainView(MainView mainView) {
        this.mainView = mainView;
    }
}
public class MainView implements RouterLayout {
    public MainView(MainViewBus mainViewBus){
        mainViewBus.setMainView(this);
    }
    
    public void someMethod(){
        Notification.show("You just invoked a method on MainView from a child view.");
    }
}
@Route("foo", layout = MainView.class)
public class FooView extends VerticalLayout {
    public FooView(MainViewBus mainViewBus){
        add(new Button("Test MainView Bus", click -> mainViewBus.getMainView().someMethod()));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.