Hi,
I have recently been assisted on displaying the slots/areas in a custom Typescript block, which uses Vite and Lit.
I have not made any progress from this again this week.
In Umbraco 13, using Angular in the controller of a html document, you can query the $scope and using code, like in the following example, get the values I had made up from the data types to help style up and control the custom block grid html.
Code in Angular Controller:
angular.module("umbraco").controller("twoColumnSectionController", function ($scope, mediaResource) {
// get the values from settings and add to scope to display values on the form
var bg = $scope.block.settingsData.backgroundColour;
if (typeof bg === 'undefined' || bg === null) {
$scope.bgcolor = "cmt-bg-none";
} else {
console.log("backgroundColour :: ", bg[0]);
$scope.bgcolor = "cmt-bg-" + bg[0];
}
var cp = $scope.block.settingsData.containerHPadding;
if (typeof cp === 'undefined' || cp === null) {
$scope.containerHPadding = "";
} else {
console.log("container padding :: ", cp[0]);
$scope.containerHPadding = cp[0];
}
var ai = $scope.block.settingsData.alignItems;
if (typeof ai === 'undefined' || ai === null) {
$scope.alignItems = "";
} else {
console.log("align items :: ", ai[0]);
$scope.alignItems = ai[0];
}
var theContainer = "container-xxl";
var cf = $scope.block.settingsData.containerFluid;
if (typeof cf === 'undefined' || cf === null) {
$scope.theContainer = "container-xxl";
} else {
console.log("container class :: ", cf[0]);
if (parseInt(cf[0]) === 1) {
$scope.theContainer = "container-fluid";
}
if (parseInt(cf[0]) === 0) {
$scope.theContainer = theContainer;
}
}
});
Code in html:
<div ng-controller="twoColumnSectionController">
<section class="cmt-section-wrap {{containerHPadding}} {{alignItems}} {{bgcolor}}">
<div class="{{theContainer}}">
<umb-block-grid-render-area-slots></umb-block-grid-render-area-slots>
</div>
</section>
</div>
This works a treat. The slots as well, can also be written as, for example:
<slot name=left"></slot><slot name="right"</slot>
Anyway, I have been assisted, with great thanks, on including the slots in the new .ts equivalent, but I am getting sometimes strange results or no results in getting block grid settings values and being able to use them in the same way in an Umbraco 15 block custom Grid.
Code of the typescript with the slots:
import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
//import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element";
import { html, customElement, LitElement, property, css, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import { UmbBlockGridTypeModel } from '@umbraco-cms/backoffice/block-grid';
//import { UmbImagingRepository } from '@umbraco-cms/backoffice/imaging'; // Import the repository
//import type { UmbMediaPickerPropertyValue } from '@umbraco-cms/backoffice/media';
const elementName = "columns-66-custom-view";
// eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name
@customElement(elementName)
// eslint-disable-next-line local-rules/umb-class-prefix
export class Columns66
extends UmbElementMixin(LitElement)
implements UmbBlockEditorCustomViewElement
{
@property({ attribute: false })
content?: UmbBlockDataType;
@property({ attribute: false })
settings?: UmbBlockDataType;
_styleElement?: HTMLLinkElement;
@state()
rowId: Map<string, string> = new Map();
@state()
blockType?: UmbBlockGridTypeModel;
override render()
{
return html`
<div class="${this.settings?.rowId ? 'align-' + this.settings?.rowId : undefined}">
<h5>Row ID snippet</h5>
<p>Alignment: ${this.settings?.rowId}</p>
</div>
${this.renderSingleSettingWithType('hideSection', 'boolean')}
${this.renderSingleSettingWithType('containerFluid', 'boolean')}
${this.renderSingleSettingWithType('rowId', 'string')}
${this.renderSingleSettingWithType('rowBackgroundColour', 'string')}
${this.renderSingleSettingWithType('containerHPadding', 'string')}
${this.renderSingleSettingWithType('alignItems', 'string')}
<h5>My Custom View</h5>
<umb-block-grid-areas-container
.areas="${this.blockType?.areas ?? []}"
.areaGridColumns="${this.blockType?.areaGridColumns}">
</umb-block-grid-areas-container>
<h5>My Custom View - left</h5>
<umb-block-grid-entries
part="area"
class="umb-block-grid__area"
.areaKey="right"></umb-block-grid-entries>
<h5>My Custom View - right</h5>
<umb-block-grid-entries
part="area"
class="umb-block-grid__area"
.areaKey="right"></umb-block-grid-entries>
<umb-block-grid-entries
part="area"
class="umb-block-grid__area"
.areaKey=${this.blockType?.areas[0].key}
.layoutColumns=${this.blockType?.areas[0].columnSpan}></umb-block-grid-entries>
<umb-block-grid-entries
part="area"
class="umb-block-grid__area"
.areaKey=${this.blockType?.areas[1].key}
.layoutColumns=${this.blockType?.areas[1].columnSpan}></umb-block-grid-entries>
`;
}
private renderSingleSettingWithType(key: string, type: 'string' | 'boolean' | 'integer')
{
if (!this.settings) return html`<p>${key} is: undefined</p><p>${key} is value: undefined</p>`;
let value = this.settings[key];
console.log("settings key and value :: ", this.settings, key, value);
switch (type)
{
case 'boolean':
value = (value as boolean) ? 'true' : 'false';
break;
case 'integer':
value = parseInt(value as string, 10);
break;
case 'string':
default:
value = (value as string)?.toString() ?? 'undefined';
break;
}
return html`
<p><strong>${key} is value: ${value}</strong></p>
`;
}
//private renderSingleSetting(key: string)
//{
// if (!this.settings) return html`<p>${key} is: undefined</p><p>${key} is value: undefined</p>`;
// const value = this.settings[key];
// return html`
// <p>${key} is: ${value ?? 'undefined'}</p>
// <p>${key} is value: ${value}</p>
//`;
//}
//private renderSettings()
//{
// if (!this.settings) return html``;
// return Object.keys(this.settings ?? {}).map(key => html`
// <p>${key} is: ${this.settings?.[key] ?? 'undefined'}</p>
// <p>${key} is value: ${this.settings?.[key]}</p>
//`);
//}
static styles = [
css`
a {
display: block;
color: inherit;
text-decoration: inherit;
border: 1px solid transparent;
border-radius: 2px;
}
a:hover {
border-color: var(--uui-color-interactive-emphasis, #3544b1);
}
.preview-alert {
background-color: var(--uui-color-danger, #f0ac00);
border: 1px solid transparent;
border-radius: 0;
margin-bottom: 20px;
padding: 8px 35px 8px 14px;
position: relative;
&, a, h4 {
color: #fff;
}
pre {
white-space: normal;
}
}
.preview-alert-warning {
background-color: var(--uui-color-danger, #f0ac00);
border-color: transparent;
color: #fff;
}
.preview-alert-info {
background-color: var(--uui-color-default, #3544b1);
border-color: transparent;
color: #fff;
}
.preview-alert-danger, .preview-alert-error {
background-color: var(--uui-color-danger, #f0ac00);
border-color: transparent;
color: #fff;
}
`
]
}
export default Columns66;
declare global
{
interface HTMLElementTagNameMap
{
[elementName]: Columns66;
}
}
Code of the Typescript for the feature:
import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
const elementName = "example-block-custom-view";
// eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name
@customElement(elementName)
// eslint-disable-next-line local-rules/umb-class-prefix
export class ExampleBlockCustomView
extends UmbElementMixin(LitElement)
implements UmbBlockEditorCustomViewElement
{
@property({ attribute: false })
content?: UmbBlockDataType;
@property({ attribute: false })
settings?: UmbBlockDataType;
override render()
{
return html`
<div class="${this.settings?.blockAlignment ? 'align-' + this.settings?.blockAlignment : undefined}">
<h5>My Custom View</h5>
<p>Name: ${this.settings?.featureName}</p>
<p>Detals: ${this.settings?.featureDetails}</p>
</div>
`;
}
static override styles = [
css`
:host {
display: block;
height: 100%;
box-sizing: border-box;
background-color: #fff;
border-radius: 0px;
padding: 0px;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
`,
];
}
export default ExampleBlockCustomView;
declare global
{
interface HTMLElementTagNameMap
{
[elementName]: ExampleBlockCustomView;
}
}
This is what is rendered. I use the alias of the settings value, but the same value is repeated for each!
I thought I would put in the Feature block on its own, and not within the Layout block to see if that would render the correct values, but no, that still repeated the first value I put in:
Thank you again for any feedback.
I think I need to start learning Typescript from the start to begin to understand this properly. Check out the new Backend Typescript Umbraco code to see how it is put together. It is a shame that the Umbraco documentation on this is as yet very shallow, in Our Umbraco, with no thorough how to to display rich text, strings, text areas and Umbraco url pickers in custom Views.
Kind regards,
Pete
This is a companion discussion topic for the original entry at https://our.umbraco.com/forum/115164-umbraco-15-custom-block-grid-displaying-data-type-values-from-a-settings-element-in-cms