Skip to content
This repository has been archived by the owner on Mar 31, 2022. It is now read-only.

Commit

Permalink
[CompositeComponent] implicitly make ids of nested components unique #…
Browse files Browse the repository at this point in the history
  • Loading branch information
glebfox committed Oct 8, 2021
1 parent 533b0ef commit b956b95
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 1 deletion.
38 changes: 37 additions & 1 deletion ui/src/main/java/io/jmix/ui/component/CompositeComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.jmix.ui.component;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.vaadin.ui.AbstractComponent;
import io.jmix.core.annotation.Internal;
import io.jmix.core.common.event.EventHub;
Expand All @@ -43,6 +44,8 @@ public class CompositeComponent<T extends Component>
protected T root;
protected Frame frame;

protected String prefixId;

protected ApplicationContext applicationContext;

// private, lazily initialized
Expand Down Expand Up @@ -130,7 +133,9 @@ protected <C> Optional<C> getInnerComponentOptional(String id) {
Preconditions.checkState(getComposition() instanceof HasComponents,
"Composition can't contain inner components");

return (Optional<C>) Optional.ofNullable(((HasComponents) getComposition()).getComponent(id));
String fullId = getFullId(id);
return (Optional<C>) Optional.ofNullable(((HasComponents) getComposition())
.getComponent(fullId));
}

/**
Expand All @@ -147,6 +152,37 @@ protected void setComposition(T composition) {
component.addAttachListener(event -> enableEventListeners());
component.addDetachListener(event -> disableEventListeners());
});

// Add id prefix to root and all nested component id to uniquely identify them
updateComponentIds();
}

protected void updateComponentIds() {
updateIdIfNeeded(root);

if (root instanceof HasComponents) {
for (Component component : ((HasComponents) root).getComponents()) {
updateIdIfNeeded(component);
}
}
}

protected void updateIdIfNeeded(Component component) {
final String id = component.getId();
if (!Strings.isNullOrEmpty(id)) {
component.setId(getFullId(id));
}
}

protected String getFullId(String id) {
return String.format("%s_%s", getPrefixId(), id);
}

protected String getPrefixId() {
if (prefixId == null) {
prefixId = UUID.randomUUID().toString();
}
return prefixId;
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import component.composite.component.TestProgrammaticCommentaryPanel
import component.composite.component.TestStepperField
import component.composite.screen.CommentaryPanelTestScreen
import component.composite.screen.EventPanelTestScreen
import component.composite.screen.MultipleStepperFieldsTestScreen
import component.composite.screen.StepperFieldTestScreen
import io.jmix.core.CoreConfiguration
import io.jmix.data.DataConfiguration
Expand All @@ -30,6 +31,7 @@ import io.jmix.ui.AppUI
import io.jmix.ui.ScreenBuilders
import io.jmix.ui.UiConfiguration
import io.jmix.ui.component.Button
import io.jmix.ui.component.impl.WindowTestHelper
import io.jmix.ui.model.InstanceContainer
import io.jmix.ui.screen.StandardOutcome
import io.jmix.ui.screen.UiControllerUtils
Expand Down Expand Up @@ -135,4 +137,20 @@ class CompositeComponentTest extends ScreenSpecification {
then: "Component should unsubscribe and event should not be handled"
screen.testEventPanel.eventCounter == 1
}

def "Multiple composite components of the same type have unique id for nested components"() {
showTestMainScreen()

def screen = (MultipleStepperFieldsTestScreen) screens.create(MultipleStepperFieldsTestScreen)
screen.show()


def window = screen.getWindow();

expect: "2 StepperField"
window.getOwnComponents().size() == 2

and: "2 StepperField + 2 * (4 nested components) = 10"
WindowTestHelper.getAllComponents(window).size() == 10
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2021 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package component.composite.screen;

import io.jmix.ui.screen.Screen;
import io.jmix.ui.screen.UiController;
import io.jmix.ui.screen.UiDescriptor;

@UiController
@UiDescriptor("multiple-stepper-fields-test-screen.xml")
public class MultipleStepperFieldsTestScreen extends Screen {
}
29 changes: 29 additions & 0 deletions ui/src/test/java/io/jmix/ui/component/impl/WindowTestHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2021 Haulmont.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.jmix.ui.component.impl;

import io.jmix.ui.component.Component;
import io.jmix.ui.component.Window;

import java.util.Map;

public class WindowTestHelper {

public static Map<String, Component> getAllComponents(Window window) {
return ((WindowImpl) window).allComponents;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
~ Copyright (c) 2008-2019 Haulmont.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<window xmlns="http://jmix.io/schema/ui/window"
xmlns:app="http://jmix.io/schema/ui/composite/test-ui-component.xsd">
<layout>
<app:testStepperField id="testStepperField1"/>
<app:testStepperField id="testStepperField2"/>
</layout>
</window>

0 comments on commit b956b95

Please sign in to comment.