I've got a custom typescript file now with a render method that gets called when I use my custom token instead of the equals sign
{% bodyText}
but dang, I don't know how to get the property value to start with.
import { UmbUfmComponentBase } from '@umbraco-cms/backoffice/ufm';
import type { UfmToken } from '@umbraco-cms/backoffice/ufm';
export class MyCustomUfmComponent extends UmbUfmComponentBase {
render(token: UfmToken) {
if (!token.text) return;
const myPropertyValue = ?; // How do I get my property value.
return `<ufm-custom-component text="${myPropertyValue.replace('foo', 'barr')}"></ufm-custom-component>`;
}
}
The base class, UmbUfmComponentBase, and its parent class UmbUfmComponentApi, seem to provide some ability to query the content api but I can't make sense of it.
by the question body you provided, you're half way there.
you will need to consume UMB_BLOCK_ENTRY_CONTEXT.
but there is a small problem is that UmbUfmComponentBase can not consume contexts so you need to create two element types
one for the UFM
and one for the context consumption and those would be in my Pull request
block-list-content-expression.component.ts for the UFM
block-list-content-expression.element.ts for the consumption which
is used isnide of the first one
(block-list-content-expression.component.ts)
now ,
because the block-list-content-expression.element.ts inherit UmbUfmElementBase its already has a property called value
what ever you put in there will be displayed in the block label so you can do something like this
Thank you for taking the time to reply! Ibrahim, it seems like this could be done with your regular expression component once it is merged in. I will watch for that.
Some gotchas:
It seems my element tag had to start with the letters "ufm", i.e.
<ufm-pdf-block-label>
I couldn't put a slash in my label right before my token or it didn't work.
"/{% bodyText}" doesn't work but "{% bodyText}" does
The link between the element and the component seems to be based of the element name, which makes sense, but it also appears that this import inside the component is critical, even though I don't understand what it does. In my mind, imports import classes that can later be used but this syntax doesn't do that and it references a .js instead of .ts file. Maybe somebody can explain what this does.
import './pdf-block-label-element.js';
Here is my extension registration, from umbraco-package.json in the "extensions" section
import { UmbUfmComponentBase } from '@umbraco-cms/backoffice/ufm';
import type { UfmToken } from '@umbraco-cms/backoffice/ufm';
import './pdf-block-label-element.js';
export class PdfBlockLabel extends UmbUfmComponentBase {
render(token: UfmToken) {
if (!token.text) return;
const attributes = super.getAttributes(token.text);
return `<ufm-pdf-block-label ${attributes}></ufm-pdf-block-label>`;
}
}
export { PdfBlockLabel as api };
And here is the element
import { UmbUfmElementBase } from '@umbraco-cms/backoffice/ufm';
import { customElement, property } from '@umbraco-cms/backoffice/external/lit';
import { UMB_BLOCK_ENTRY_CONTEXT } from '@umbraco-cms/backoffice/block';
const elementName = 'ufm-pdf-block-label';
@customElement(elementName)
export class PdfBlockLabelElement extends UmbUfmElementBase {
@property()
alias?: string;
constructor() {
super();
this.consumeContext(UMB_BLOCK_ENTRY_CONTEXT, (context) => {
this.observe(
context.content,
(value) => {
if (this.alias !== undefined && value !== undefined && typeof value === 'object') {
const record = (value as Record<string, unknown>)[this.alias];
// Whatever you want to do to the value here -- in my case lowercase with some string replacement.
this.value = record.toString().toLowerCase().replace(" ", "-");
} else {
this.value = value;
}
},
'observeValue',
);
});
}
}
export { PdfBlockLabelElement as element };
declare global {
interface HTMLElementTagNameMap {
[elementName]: PdfBlockLabelElement;
}
}
v14 - Umbraco Flavored Markup Component - Simple Example?
I want to do some simple string replacement on a block label.
For a typical block label we do something like
I want to do something like
I've been been reading in the docs about custom UFM Components https://docs.umbraco.com/umbraco-cms/reference/umbraco-flavored-markdown#custom-ufm-components
I've got a custom typescript file now with a render method that gets called when I use my custom token instead of the equals sign
but dang, I don't know how to get the property value to start with.
The base class, UmbUfmComponentBase, and its parent class UmbUfmComponentApi, seem to provide some ability to query the content api but I can't make sense of it.
I feel like I'm sooo close.
you need to import the context e.g. for Block Grid you would import
as per my pull request here
https://github.com/umbraco/Umbraco.CMS.Backoffice/pull/2345/files (hope fully it will get merged soon)
by the question body you provided, you're half way there.
you will need to consume
UMB_BLOCK_ENTRY_CONTEXT
. but there is a small problem is thatUmbUfmComponentBase
can not consume contexts so you need to create two element typesone for the UFM and one for the context consumption and those would be in my Pull request
block-list-content-expression.component.ts
for the UFMblock-list-content-expression.element.ts
for the consumption which is used isnide of the first one (block-list-content-expression.component.ts
)now ,
because the
block-list-content-expression.element.ts
inheritUmbUfmElementBase
its already has a property calledvalue
what ever you put in there will be displayed in the block label so you can do something like this
and then youre done , take my Pull request as reference
Thank you for taking the time to reply! Ibrahim, it seems like this could be done with your regular expression component once it is merged in. I will watch for that.
I was able to get my custom component working with your explanation, pull request, and from the source code of the vanilla ufm label. Some explanation on why this is all necessary was found in a recent discord chat https://discord-chats.umbraco.com/t/23104860/context-api-umbraco-cms and another possible solution https://discord-chats.umbraco.com/t/23111780/but-i-do-not-think-you-need-to-do-any-different-for-your-ufm
Some gotchas: It seems my element tag had to start with the letters "ufm", i.e.
I couldn't put a slash in my label right before my token or it didn't work.
The link between the element and the component seems to be based of the element name, which makes sense, but it also appears that this import inside the component is critical, even though I don't understand what it does. In my mind, imports import classes that can later be used but this syntax doesn't do that and it references a .js instead of .ts file. Maybe somebody can explain what this does.
Here is my extension registration, from umbraco-package.json in the "extensions" section
Here is the referenced component
And here is the element
With v15 this code doesn't work anymore since context.content isn't public or even an observable variable anymore.
Any ideas Niels Lyngs?
Try something like this :
Thanks Ibrahim!
That is what I needed. Since I was in a constructor I had to wrap it in a .then(() => {}); block but it seems to be working again.
Much appreciated.
Note: the new UFM 'Filters' get close to providing what I need here but no '.replace()' filter yet
is working on a reply...