Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui5-tooling-modules): named aggregations can also be marked as default aggregation #1096

Merged
merged 3 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions packages/ui5-tooling-modules/lib/utils/WebComponentRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class RegistryEntry {
}

#extractUi5Type(typeInfo) {
// [Simple type]:
// some types are given as a union type, e.g. "string | undefined"
// TODO: are there combinations of arrays and other types/undefined? e.g. "Array<number> | undefined"
// Does that make sense? Probably should be an empty array instead of undefined?
Expand All @@ -143,18 +144,24 @@ class RegistryEntry {
};
}

// UI5 normally accepts only one type for a property, except if "any" is used
// in this case we just use the first one as the primary type
// UI5 only accepts one type for a property/aggregation, in this case we just use the first one as the primary type.
parsedType = types[0];
}

// check if we have an array type
const arrayTypeMatch = parsedType?.match(/Array<(.*)>/i);
const multiple = !!arrayTypeMatch;
parsedType = arrayTypeMatch?.[1] || parsedType;

// complex types have a reference to other things, e.g. enums
if (typeInfo?.references) {
// [Complex types]:
// we have a reference to other things -> enums, interfaces, classes
if (typeInfo?.references?.length > 0) {
// Since the UI5 runtime only allows for 1 single type per property/aggregation, we take the first reference
parsedType = typeInfo.references[0].name;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok - this is interesting because the Luigi guys also used multiple types. So, the first type wins and should be then the most generic type - an alternative would be to use object in such cases.


// TODO: Investigate if this fallback can be omitted, I suspect it is not needed.
// The string based type "arrayTypeMatch[1]" might contain TypeScript generics, which are not known (and irrelevant) to UI5 -> e.g. P13nPopup
parsedType ??= arrayTypeMatch?.[1] || parsedType;

// case 2: enum type -> easy
if (this.enums[parsedType]) {
return {
Expand All @@ -164,13 +171,10 @@ class RegistryEntry {
};
}

// case 3: interface type -> theoretically this should this be a 0..n aggregation... but really?
// case 3: interface or class type
const interfaceOrClassType = this.#checkForInterfaceOrClassType(parsedType);

if (interfaceOrClassType) {
// TODO: How should this be wired for properties?
// Aggregations can have an interface/class type, but properties do not.
// A property of this typing could be considered a calculated field...?
return {
isInterfaceOrClassType: true,
origType: parsedType,
Expand Down Expand Up @@ -225,7 +229,7 @@ class RegistryEntry {
#processMembers(classDef, ui5metadata, propDef) {
// field -> property
if (propDef.kind === "field") {
let ui5TypeInfo = this.#extractUi5Type(propDef.type, propDef.name);
let ui5TypeInfo = this.#extractUi5Type(propDef.type);

// [ Accessibility ]
// 1. ACC attributes have webc internal typing and will be defaulted to "object" ob UI5 side.
Expand Down Expand Up @@ -316,11 +320,16 @@ class RegistryEntry {
}
}

// "default" slot becomes default aggregation
// The "default" slot will most likely be transformed into the "content" in UI5
if (aggregationName === "default") {
// we call it "content" in ui5 though
aggregationName = "content";
// default slot has no name
// but if a "_ui5propertyName" is defined, we regard it as a named aggregation!
if (slotDef._ui5propertyName) {
aggregationName = slotDef._ui5propertyName;
} else {
aggregationName = "content";
}

// on webc level the default slot has no name
slotName = undefined;

ui5metadata.defaultAggregation = aggregationName;
Expand Down
2 changes: 2 additions & 0 deletions showcases/ui5-tsapp-webc/webapp/view/Main.view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<VBox alignItems="Center" justifyContent="Center" height="100%">
<webc:Input value="Hello World 123" change="onBoo" />
<webc:AvatarGroup type="Individual">
<!-- Example: the default aggregation of the AvatarGroup is called "items"
It is not need to explicitly name this aggregation here. -->
<webc:Avatar initials="PM" colorScheme="Accent1" />
<webc:Avatar initials="XX" colorScheme="Accent4" shape="Square" />
<webc:Avatar icon="ai" colorScheme="Accent7" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
</fiori:DynamicPageHeader>
</fiori:headerArea>

<webc:List content="{dpModel>/items}" headerText="Products" selectionMode="None">
<webc:List items="{dpModel>/items}" headerText="Products" selectionMode="None">
<webc:ListItemStandard icon="slim-arrow-right" iconEnd="true" description="{dpModel>productID}" additionalText="{dpModel>price}" text="{dpModel>productName}">
<webc:image>
<webc:Avatar size="S" shape="Square" colorScheme="Accent10">
Expand Down
Loading