How do I use Areas within custom Block Previews in the backoffice?

Heya :waving_hand:
I am building a navigation using block grid that contains an element type for the layout/areas (contains 4 column areas) and then each area can then add an element type of Navigation Link.

Current Screenshot

It currently looks like this in the backoffice which is OK, but I wanted to see if we can use a custom block view to help them get a more visually representation of their navigation

Goal

The goal is to have a custom backoffice block preview for the outer layout block so that I can then render 4 areas inside it, which in turn will then render the child Navigation Link blocks.

Ideally I want it to do the following:

  • Have a similar look and feel to the site - hence the custom block view
  • Render 4 areas
  • Each area can drag and drop the blocks around within the area and to other area columns
  • Has UI to add a new link in each area

Taking a look at the UmbBlockEditorCustomViewElement and the UmbBlockEditorCustomViewProperties interfaces from Umbraco. I don’t see anything I could use.

So any advice or pointers on how this could be achieved with areas.

Thanks,
Warren :smiley:

1 Like

Hey @warren!

In BlockPreview I have to render the following in the backoffice to get access to areas:

<umb-block-grid-areas-container slot="areas"></umb-block-grid-areas-container>

This web component does a lot of heavy lifting as the block context knows what the areas are.

I’ve found that it’s not currently set up to handle multiple nested areas, so that will need adding in every block that has areas.

You can also render a specific named area like so:

<umb-block-grid-entries
  part="area"
  class="umb-block-grid__area"
  .areaKey="{AREA KEY}">
</umb-block-grid-entries>

Hope that’s helpful and I’ve understood correctly!

1 Like

Heya Rick :waving_hand:
Thanks for that speeeedy reply !

The day is coming to an end now, so I will try this in the morning and see how it goes and report back on how successful or not I am.

Heya @rickbutterfield :waving_hand:

This works fine and renders out the grid areas nicely, but trying to use the following to render out a very specific grid area does not work for me :upside_down_face:

Even without it bound to a property and using the attribute value area-key="column-one"

Think I need to do some source code diving :diving_mask: and look at CMS repo and perhaps your Block Preview package for more bits.

Ah, area-key (or .areaKey, whichever works!) needs to be the Guid key of the area, not a named one

Ah OK thanks - I had assumed it was the alias of the area and not a GUID. Will grab the hardcoded value for now to give it a quick try

OK that works nicely and they drag between the areas nicely as well :tada:
So thanks Rick !!

Suggestion

It is a shame the JSON for the layout property does not include the alias that is set in the backoffice when configuring the areas, as it would be nicer/easier/friendlier to get an area by its alias as opposed to a GUID/Key.

JSON of Layout property

{
  "$type": "BlockGridLayoutItem",
  "columnSpan": 12,
  "rowSpan": 1,
  "areas": [
    {
      "key": "69af0eda-a73d-4feb-9512-465f4c66e21e",
      "items": [
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "85f597b8-4434-4aee-8380-cc46db262696",
          "settingsKey": null
        },
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "387f89db-629d-4b40-8bbd-adc1fc7eaae9",
          "settingsKey": null
        },
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "93d3ec2f-dad6-406e-b12a-bd25012ea19a",
          "settingsKey": null
        },
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "a27a3b15-5e46-4a7f-b558-a429d260f6e4",
          "settingsKey": null
        }
      ]
    },
    {
      "key": "24e58942-c5df-4c02-894f-7f94f55f2e30",
      "items": [
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "dfc271a5-7b0a-4a2d-9506-27f8a1ab72c9",
          "settingsKey": null
        },
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "dc238d32-cfc7-4a00-b43d-4a1ade8ed0d9",
          "settingsKey": null
        }
      ]
    },
    {
      "key": "2f294f12-d8c3-434a-87b3-36f897093976",
      "items": [
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "c516e473-67a3-4c11-91c3-5fbe2c485579",
          "settingsKey": null
        },
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "f18bef25-b631-46d1-afa8-75a27382f9d7",
          "settingsKey": null
        }
      ]
    },
    {
      "key": "99d95040-279f-4dcc-9f9c-03b74dec2037",
      "items": [
        {
          "columnSpan": 3,
          "rowSpan": 1,
          "areas": [],
          "contentUdi": null,
          "settingsUdi": null,
          "contentKey": "94f1c69a-c1ae-4c36-af5b-fd39d5c370a7",
          "settingsKey": null
        }
      ]
    }
  ],
  "contentUdi": null,
  "settingsUdi": null,
  "contentKey": "84d9cf67-01d7-4e62-88e5-4feed0477c94",
  "settingsKey": null
}

Solution for now

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 UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';

@customElement('footer-layout-block-custom-view')
export class FooterLayoutBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
    
    @property({ attribute: false })
    content?: UmbBlockDataType & {
        image: Array<{ mediaKey: string }>;
    }

    @property({ attribute: false })
    label?: string;

    @property({ attribute: false })
    settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    @property({ attribute: false })
    layout?: UmbBlockGridLayoutModel;

    constructor() {
        super();
    }

    render() {
        return html`
            <fieldset>
                <legend>${this.label ?? 'Footer Layout'}</legend>
                <figure>
                    <div id="grid">
                        <div class="area area-1">
                            Some SVG logo to put here
                        </div>
                        <div class="area area-2">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[0]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-3">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[1]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-4">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[2]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-5">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[3]?.key}"></umb-block-grid-entries>
                        </div>
                    </div>
                </figure>
            </fieldset>
        `;
    }

    static styles = [
        commonStyles,
        css`
            fieldset {
                background: var(--colour-echo);
                padding: 15px 15px 20px 15px;
            }
            
            #grid {
                display: grid;
                grid-column-gap: 10px;
                grid-template-columns: repeat(5, 1fr);
            }

            .area {
                border: 1px solid red;
                min-height: 100px;
            }
        `,
    ];
    
}
export default FooterLayoutBlockCustomView;

declare global {
    interface HTMLElementTagNameMap {
        'footer-layout-block-custom-view': FooterLayoutBlockCustomView;
    }
}

Screenshot

3 Likes

Final Result

Here is a screenshot of the navigation block preview using two custom block previews

  • Footer Layout
  • Footer Link

Note: This is not for Umbraco as the client, it was just another SVG I could grab quickly to show the concept off without using the clients logo.

footer-layout.ts

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 UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';

@customElement('footer-layout-block-custom-view')
export class FooterLayoutBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
    
    @property({ attribute: false })
    content?: UmbBlockDataType;

    @property({ attribute: false })
    label?: string;

    @property({ attribute: false })
    settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    @property({ attribute: false })
    layout?: UmbBlockGridLayoutModel;

    constructor() {
        super();
    }

    render() {
        return html`
            <fieldset>
                <legend>${this.label ?? 'Footer Layout'}</legend>
                <figure>
                    <div id="grid">
                        <div class="area area-1">
                            <svg width="187" height="50" viewBox="0 0 187 50" fill="none" xmlns="http://www.w3.org/2000/svg" class="logo">
                                <path d="M1.49169e-05 24.9701C0.0149492 11.1559 11.2306 -0.0149193 25.0299 1.49568e-05C38.8292 0.0149492 50.0149 11.2306 50 25.0299C49.9851 38.8292 38.7993 50 25 50C11.1858 49.9851 -0.0149194 38.7844 1.49169e-05 24.9701ZM24.4922 33.5275C22.5508 33.5872 20.6093 33.408 18.7127 33.0048C17.3089 32.721 16.129 31.7802 15.5466 30.466C14.9791 29.1667 14.7103 27.1505 14.7252 24.4325C14.7402 23.0138 14.8298 21.595 14.994 20.1912C15.1583 18.8172 15.3226 17.6822 15.4719 16.7862L15.6362 15.905C15.6362 15.8752 15.6362 15.8602 15.6362 15.8304C15.6362 15.5765 15.457 15.3674 15.2181 15.3226L11.9922 14.8148H11.9474C11.7085 14.8148 11.5143 14.9791 11.4546 15.2031C11.3949 15.4122 11.365 15.5615 11.2754 16.0544C11.0962 17.0102 10.917 17.9361 10.7378 19.2802C10.5436 20.7437 10.4241 22.2222 10.3793 23.7007C10.3047 24.7312 10.3047 25.7617 10.3793 26.7921C10.454 29.5251 10.9319 31.7204 11.7832 33.3483C12.6344 34.9761 14.1129 36.1559 16.1738 36.8728C18.2348 37.5896 21.1022 37.948 24.7909 37.9331H25.2539C28.9427 37.948 31.81 37.6045 33.871 36.8728C35.9319 36.1559 37.3955 34.9761 38.2617 33.3483C39.1278 31.7055 39.5908 29.5251 39.6655 26.7921C39.7402 25.7617 39.7402 24.7312 39.6655 23.7007C39.6207 22.2222 39.5012 20.7437 39.3071 19.2802C39.1129 17.951 38.9486 17.0251 38.7694 16.0544C38.6798 15.5615 38.635 15.4122 38.5902 15.2031C38.5305 14.9791 38.3363 14.8148 38.0974 14.8148H38.0078L34.782 15.3226C34.543 15.3674 34.3638 15.5765 34.3638 15.8304C34.3638 15.8602 34.3638 15.8752 34.3638 15.905L34.543 16.7862C34.7073 17.6822 34.8716 18.8172 35.0359 20.1762C35.2001 21.5801 35.2897 22.9988 35.3047 24.4176C35.3345 27.1356 35.0508 29.1368 34.4833 30.451C33.9158 31.7503 32.7509 32.6912 31.362 32.9898C29.4654 33.3931 27.5239 33.5723 25.5824 33.5126L24.4922 33.5275Z" fill="#283A97" id="circle-logo"></path>
                                <path d="M171.774 27.046C171.774 22.058 173.208 18.5484 178.973 18.5484C184.737 18.5484 186.171 22.058 186.171 27.046C186.171 32.0341 184.737 35.5436 178.973 35.5436C173.208 35.5436 171.774 32.0341 171.774 27.046ZM182.512 27.046C182.512 23.5813 182.064 21.595 178.987 21.595C175.911 21.595 175.463 23.5813 175.463 27.046C175.463 30.5108 175.926 32.497 178.987 32.497C182.049 32.497 182.512 30.4958 182.512 27.046Z" fill="#283A97"></path>
                                <path d="M72.0131 34.9014C72.1027 35.0507 72.2521 35.1403 72.4313 35.1403H73.7754C74.0442 35.1403 74.2533 34.9313 74.2533 34.6624V19.4145C74.2533 19.1457 74.0442 18.9366 73.7754 18.9366H71.0872C70.8184 18.9366 70.6093 19.1457 70.6093 19.4145V31.5113C69.4594 32.1535 68.1601 32.482 66.8459 32.4522C65.1284 32.4522 64.2772 31.7055 64.2772 30.0478V19.4145C64.2772 19.1457 64.0681 18.9366 63.7993 18.9366H61.126C60.8572 18.9366 60.6481 19.1457 60.6481 19.4145V30.3763C60.6481 33.4826 62.1117 35.5286 66.2186 35.5286C68.1003 35.5137 69.9373 34.9163 71.4755 33.8411L71.9534 34.9163L72.0131 34.9014Z" fill="#283A97"></path>
                                <path d="M102.27 23.7007C102.27 20.6243 100.747 18.5484 96.9086 18.5484C95.0567 18.5484 93.2497 19.1159 91.7115 20.1464C91.0245 19.1458 89.7252 18.5484 87.5597 18.5484C85.7975 18.5783 84.08 19.1756 82.6613 20.236L82.1834 19.1607C82.0938 19.0114 81.9444 18.9068 81.7652 18.9068H80.4211C80.1523 18.9068 79.9432 19.1159 79.9432 19.3847V34.6326C79.9432 34.9014 80.1523 35.1105 80.4211 35.1105H83.1093C83.3781 35.1105 83.5872 34.9014 83.5872 34.6326V22.5657C84.6177 21.9534 85.7975 21.6249 86.9922 21.6249C88.4558 21.6249 89.2921 22.1625 89.2921 23.7157V34.6774C89.2921 34.9462 89.5012 35.1553 89.77 35.1553H92.4582C92.727 35.1553 92.9361 34.9462 92.9361 34.6774V22.5657C93.9516 21.9385 95.1463 21.6099 96.3411 21.6099C97.7748 21.6099 98.641 22.1476 98.641 23.7007V34.6625C98.641 34.9313 98.85 35.1404 99.1189 35.1404H101.807C102.076 35.1404 102.285 34.9313 102.285 34.6625L102.27 23.7007Z" fill="#283A97"></path>
                                <path d="M110.573 33.856C112.097 34.9761 113.934 35.5735 115.83 35.5436C120.565 35.5436 122.312 32.3626 122.312 27.046C122.312 21.7294 120.565 18.5484 115.83 18.5484C114.292 18.5633 112.784 18.9964 111.484 19.8178V14.9044C111.484 14.6356 111.275 14.4265 111.007 14.4265H108.318C108.05 14.4265 107.841 14.6356 107.841 14.9044V34.6625C107.841 34.9313 108.05 35.1404 108.318 35.1404H109.662C109.842 35.1404 109.991 35.0508 110.081 34.9014L110.573 33.856ZM114.979 32.4522C113.754 32.4522 112.545 32.1386 111.484 31.5113V22.5657C112.545 21.9534 113.754 21.6248 114.979 21.6248C118.16 21.6248 118.638 24.0591 118.638 27.0311C118.638 30.003 118.16 32.4522 114.979 32.4522Z" fill="#283A97"></path>
                                <path d="M135.738 21.7294C135.32 21.6697 134.901 21.6398 134.468 21.6547C133.02 21.595 131.586 21.9385 130.317 22.6254V34.6625C130.317 34.9313 130.108 35.1404 129.839 35.1404H127.151C126.882 35.1404 126.673 34.9313 126.673 34.6625V19.4146C126.673 19.1458 126.882 18.9367 127.151 18.9367H128.495C128.674 18.9367 128.823 19.0263 128.913 19.1756L129.391 20.2509C130.869 19.1308 132.676 18.5335 134.528 18.5633C134.946 18.5633 135.379 18.5932 135.798 18.6679C136.051 18.6679 136.246 19.0711 136.246 19.325V21.2664C136.246 21.5352 136.036 21.7443 135.768 21.7443L135.738 21.7294Z" fill="#283A97"></path>
                                <path d="M145.027 27.6583C143.429 27.8525 142.458 28.4648 142.458 30.1523C142.458 31.3919 142.996 32.5568 144.952 32.5568C146.192 32.5717 147.401 32.1983 148.417 31.4815V27.285L145.027 27.6583ZM149.313 33.856C147.924 34.9463 146.207 35.5436 144.429 35.5436C140.248 35.5436 138.859 32.9451 138.859 30.3465C138.859 26.8369 141.129 25.3584 144.788 25.0598L148.432 24.776V23.9696C148.432 22.3118 147.655 21.6697 145.251 21.6697C143.743 21.6697 142.249 21.9236 140.83 22.4015C140.786 22.4164 140.726 22.4164 140.681 22.4015C140.412 22.4015 140.203 22.1924 140.203 21.9236V19.773C140.203 19.5639 140.323 19.3847 140.517 19.3101C142.13 18.7724 143.817 18.5036 145.52 18.5036C150.836 18.5036 152.061 20.8334 152.061 24.2832V34.6326C152.061 34.9014 151.852 35.1105 151.583 35.1105H150.239C150.06 35.1105 149.91 35.0209 149.821 34.8716L149.313 33.856Z" fill="#283A97"></path>
                                <path d="M167.802 31.81C167.846 31.81 167.906 31.81 167.951 31.81C168.22 31.81 168.429 32.0191 168.429 32.2879V34.4384C168.429 34.6326 168.309 34.8118 168.13 34.8865C166.801 35.3644 165.382 35.6033 163.964 35.5734C158.214 35.5734 156.452 32.1386 156.452 27.0758C156.452 22.0131 158.214 18.5782 163.964 18.5782C165.367 18.5484 166.786 18.7574 168.115 19.2353C168.294 19.31 168.414 19.4892 168.414 19.6834V21.8488C168.414 22.1177 168.205 22.3267 167.936 22.3267C167.876 22.3417 167.832 22.3417 167.772 22.3267C166.607 21.9534 165.382 21.7742 164.158 21.7891C161.007 21.7891 160.096 23.9396 160.096 27.0758C160.096 30.212 161.007 32.3626 164.158 32.3626C165.382 32.3775 166.607 32.1983 167.772 31.8249" fill="#283A97"></path>
                            </svg>
                        </div>
                        <div class="area area-2">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[0]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-3">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[1]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-4">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[2]?.key}"></umb-block-grid-entries>
                        </div>
                        <div class="area area-5">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[3]?.key}"></umb-block-grid-entries>
                        </div>
                    </div>
                </figure>
            </fieldset>
        `;
    }

    static styles = [
        commonStyles,
        css`
            fieldset {
                background: var(--colour-echo);
                padding: 15px 15px 20px 15px;
            }
            
            .logo path {
                fill: white;
            }

            #grid {
                display: grid;
                grid-column-gap: 10px;
                grid-template-columns: repeat(5, 1fr);
            }

            .area {
                min-height: 100px;
            }
        `,
    ];
    
}
export default FooterLayoutBlockCustomView;

declare global {
    interface HTMLElementTagNameMap {
        'footer-layout-block-custom-view': FooterLayoutBlockCustomView;
    }
}

footer-link.ts

import { html, customElement, LitElement, property, css, nothing } from '@umbraco-cms/backoffice/external/lit';
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
import { type UmbBlockDataType } from '@umbraco-cms/backoffice/block';
import { type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';
import { UmbLinkPickerLink } from '@umbraco-cms/backoffice/multi-url-picker';

@customElement('footer-link-block-custom-view')
export class FooterLinkBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
    
    @property({ attribute: false })
    content?: UmbBlockDataType & {
        link: Array<UmbLinkPickerLink>;
    }

    @property({ attribute: false })
    label?: string;

    @property({ attribute: false })
    settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    @property({ attribute: false })
    layout?: UmbBlockGridLayoutModel;

    constructor() {
        super();
    }

    render() {
        const link = this.content?.link[0];
        
        return html`
            <div class="container">
                ${this.content?.link[0]?.name}
                ${this.#renderLinkTypeTag(link?.type)}
            </div>
        `;
    }

    #renderLinkTypeTag(linkType: UmbLinkPickerLink['type']) {
        if (!linkType) return nothing;
        
        switch (linkType.toLowerCase()) {
            case 'external':
                return html`<uui-tag color="warning">External</uui-tag>`;
            case 'document':
                return html`<uui-tag>Document</uui-tag>`;
            case 'media':
                return html`<uui-tag>Media</uui-tag>`;
            default:
                return html`<uui-tag>${linkType}</uui-tag>`;
        }
    }

    static styles = [
        commonStyles,
        css`
            :host {
                color:white;
                background:rgba(255,255,255,0.1);
                height:100%;
            }

            div.container {
                height:100%;
                display:flex;
                align-items:center;
                justify-content: space-between;
                border: 1px dashed rgba(255,255,255,0.4);
                padding: 0 10px;
            }
        `,
    ];
    
}
export default FooterLinkBlockCustomView;

declare global {
    interface HTMLElementTagNameMap {
        'footer-link-block-custom-view': FooterLinkBlockCustomView;
    }
}

manifest.ts

export const manifests: Array<UmbExtensionManifest> = [
    {
        name: "Block Preview - Footer Layout",
        alias: "client.blockpreview.footerLayout",
        type: "blockEditorCustomView",
        forContentTypeAlias: "footerColumnLayoutBlock",
        js: () => import("./footer-layout"),
    },
    {
        name: "Block Preview - Footer Link",
        alias: "client.blockpreview.footerLink",
        type: "blockEditorCustomView",
        forContentTypeAlias: "footerLinkBlock",
        js: () => import("./footer-link"),
    }
];
1 Like

Spoke too soon

It seems when using my custom block previews to add a new link block, it then causes the front end rendering to crash :fire:

I have disabled my custom block previews and added a new link block without any error there, so it is down to my two custom blocktype previews somehow not working as I would expect.

Error :collision:

InvalidOperationException: Nullable object must have a value.

InvalidOperationException: Nullable object must have a value.
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockPropertyValueCreatorBase<TBlockModel, TBlockItemModel, TBlockLayoutItem, TBlockConfiguration, TBlockValue>+<>c__DisplayClass14_0.<CreateBlockModel>g__CreateBlockItem|3(TBlockLayoutItem layoutItem)
System.Linq.Enumerable+ArraySelectIterator<TSource, TResult>.MoveNext()
System.Linq.Enumerable+IEnumerableWhereIterator<TSource>.ToList()
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockGridPropertyValueCreator+<>c__DisplayClass3_1.<CreateBlockModel>b__4(BlockGridLayoutAreaItem area)
System.Linq.Enumerable+ArraySelectIterator<TSource, TResult>.MoveNext()
System.Linq.Enumerable+IEnumerableWhereIterator<TSource>.ToArray()
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockPropertyValueCreatorBase<TBlockModel, TBlockItemModel, TBlockLayoutItem, TBlockConfiguration, TBlockValue>+<>c__DisplayClass14_0.<CreateBlockModel>g__CreateBlockItem|3(TBlockLayoutItem layoutItem)
System.Linq.Enumerable+IEnumerableWhereSelectIterator<TSource, TResult>.MoveNext()
System.Linq.Enumerable+IEnumerableWhereIterator<TSource>.ToList()
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockPropertyValueCreatorBase<TBlockModel, TBlockItemModel, TBlockLayoutItem, TBlockConfiguration, TBlockValue>.CreateBlockModel(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, BlockEditorData<TBlockValue, TBlockLayoutItem> converted, bool preview, IEnumerable<TBlockConfiguration> blockConfigurations, CreateEmptyBlockModel createEmptyModel, CreateBlockModelFromItems createModelFromItems, EnrichBlockItemModelFromConfiguration enrichBlockItem)
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockPropertyValueCreatorBase<TBlockModel, TBlockItemModel, TBlockLayoutItem, TBlockConfiguration, TBlockValue>.CreateBlockModel(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, string intermediateBlockModelValue, bool preview, IEnumerable<TBlockConfiguration> blockConfigurations, CreateEmptyBlockModel createEmptyModel, CreateBlockModelFromItems createModelFromItems, EnrichBlockItemModelFromConfiguration enrichBlockItem)
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockGridPropertyValueCreator.CreateBlockModel(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, string intermediateBlockModelValue, bool preview, BlockGridBlockConfiguration[] blockConfigurations, Nullable<int> gridColumns)
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockGridPropertyValueConverter.ConvertIntermediateToBlockGridModel(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
Umbraco.Cms.Core.PropertyEditors.ValueConverters.BlockGridPropertyValueConverter.ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
Umbraco.Cms.Infrastructure.HybridCache.PublishedProperty.GetValue(string culture, string segment)
Umbraco.Extensions.PublishedPropertyExtension.Value<T>(IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string culture, string segment, Fallback fallback, T defaultValue)
Umbraco.Extensions.PublishedContentExtensions.Value<T>(IPublishedContent content, IPublishedValueFallback publishedValueFallback, string alias, string culture, string segment, Fallback fallback, T defaultValue)
Umbraco.Cms.Web.Common.PublishedModels.Home.get_FooterNavigation() in Home.generated.cs
+
		public virtual global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel FooterNavigation => this.Value<global::Umbraco.Cms.Core.Models.Blocks.BlockGridModel>(_publishedValueFallback, "footerNavigation");
AspNetCore.Views_Partials_Footer.ExecuteAsync() in Footer.cshtml

Time to investigate :detective:

I will try and play spot the difference between the two stored payloads of JSON to see what differs and see if I can step into Umbraco CMS source code for the BlockGridPropertyValueConverter and see if I get any pointers or clues.

Found the diff

Looking at the two payloads that I get from the server after saving the content node I can see the difference in the JSON for the BlockGrid.

{
+   "columnSpan": 3, # Using the default out of the box experience
-   "columnSpan": null, # Using my custom block previews
    "rowSpan": 1,
    "areas": [],
    "contentUdi": null,
    "settingsUdi": null,
    "contentKey": "58432508-2fd4-4059-9af7-839dd18d969e",
    "settingsKey": null
}

Fix

Looking at the source code of the component there is a property layoutColumns that I needed to set.

<umb-block-grid-entries 
    .areaKey="${this.layout?.areas?.[0]?.key}" 
    .layoutColumns=${this.layout?.columnSpan}></umb-block-grid-entries>

Updated footer-layout.ts

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 UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid';
import type { UmbBlockEditorCustomViewConfiguration, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view';
import { commonStyles } from './common-styles';

@customElement('footer-layout-block-custom-view')
export class FooterLayoutBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement {
    
    @property({ attribute: false })
    content?: UmbBlockDataType;

    @property({ attribute: false })
    label?: string;

    @property({ attribute: false })
    settings?: UmbBlockDataType;

    @property({ attribute: false })
    config?: UmbBlockEditorCustomViewConfiguration;

    @property({ attribute: false })
    layout?: UmbBlockGridLayoutModel;

    constructor() {
        super();
    }

    render() {
        return html`
            <fieldset>
                <legend>${this.label ?? 'Footer Layout'}</legend>
                <figure>
                    <div id="grid">
                        <div class="area area-1">
                            <svg width="187" height="50" viewBox="0 0 187 50" fill="none" xmlns="http://www.w3.org/2000/svg" class="logo">
                                <path d="M1.49169e-05 24.9701C0.0149492 11.1559 11.2306 -0.0149193 25.0299 1.49568e-05C38.8292 0.0149492 50.0149 11.2306 50 25.0299C49.9851 38.8292 38.7993 50 25 50C11.1858 49.9851 -0.0149194 38.7844 1.49169e-05 24.9701ZM24.4922 33.5275C22.5508 33.5872 20.6093 33.408 18.7127 33.0048C17.3089 32.721 16.129 31.7802 15.5466 30.466C14.9791 29.1667 14.7103 27.1505 14.7252 24.4325C14.7402 23.0138 14.8298 21.595 14.994 20.1912C15.1583 18.8172 15.3226 17.6822 15.4719 16.7862L15.6362 15.905C15.6362 15.8752 15.6362 15.8602 15.6362 15.8304C15.6362 15.5765 15.457 15.3674 15.2181 15.3226L11.9922 14.8148H11.9474C11.7085 14.8148 11.5143 14.9791 11.4546 15.2031C11.3949 15.4122 11.365 15.5615 11.2754 16.0544C11.0962 17.0102 10.917 17.9361 10.7378 19.2802C10.5436 20.7437 10.4241 22.2222 10.3793 23.7007C10.3047 24.7312 10.3047 25.7617 10.3793 26.7921C10.454 29.5251 10.9319 31.7204 11.7832 33.3483C12.6344 34.9761 14.1129 36.1559 16.1738 36.8728C18.2348 37.5896 21.1022 37.948 24.7909 37.9331H25.2539C28.9427 37.948 31.81 37.6045 33.871 36.8728C35.9319 36.1559 37.3955 34.9761 38.2617 33.3483C39.1278 31.7055 39.5908 29.5251 39.6655 26.7921C39.7402 25.7617 39.7402 24.7312 39.6655 23.7007C39.6207 22.2222 39.5012 20.7437 39.3071 19.2802C39.1129 17.951 38.9486 17.0251 38.7694 16.0544C38.6798 15.5615 38.635 15.4122 38.5902 15.2031C38.5305 14.9791 38.3363 14.8148 38.0974 14.8148H38.0078L34.782 15.3226C34.543 15.3674 34.3638 15.5765 34.3638 15.8304C34.3638 15.8602 34.3638 15.8752 34.3638 15.905L34.543 16.7862C34.7073 17.6822 34.8716 18.8172 35.0359 20.1762C35.2001 21.5801 35.2897 22.9988 35.3047 24.4176C35.3345 27.1356 35.0508 29.1368 34.4833 30.451C33.9158 31.7503 32.7509 32.6912 31.362 32.9898C29.4654 33.3931 27.5239 33.5723 25.5824 33.5126L24.4922 33.5275Z" fill="#283A97" id="circle-logo"></path>
                                <path d="M171.774 27.046C171.774 22.058 173.208 18.5484 178.973 18.5484C184.737 18.5484 186.171 22.058 186.171 27.046C186.171 32.0341 184.737 35.5436 178.973 35.5436C173.208 35.5436 171.774 32.0341 171.774 27.046ZM182.512 27.046C182.512 23.5813 182.064 21.595 178.987 21.595C175.911 21.595 175.463 23.5813 175.463 27.046C175.463 30.5108 175.926 32.497 178.987 32.497C182.049 32.497 182.512 30.4958 182.512 27.046Z" fill="#283A97"></path>
                                <path d="M72.0131 34.9014C72.1027 35.0507 72.2521 35.1403 72.4313 35.1403H73.7754C74.0442 35.1403 74.2533 34.9313 74.2533 34.6624V19.4145C74.2533 19.1457 74.0442 18.9366 73.7754 18.9366H71.0872C70.8184 18.9366 70.6093 19.1457 70.6093 19.4145V31.5113C69.4594 32.1535 68.1601 32.482 66.8459 32.4522C65.1284 32.4522 64.2772 31.7055 64.2772 30.0478V19.4145C64.2772 19.1457 64.0681 18.9366 63.7993 18.9366H61.126C60.8572 18.9366 60.6481 19.1457 60.6481 19.4145V30.3763C60.6481 33.4826 62.1117 35.5286 66.2186 35.5286C68.1003 35.5137 69.9373 34.9163 71.4755 33.8411L71.9534 34.9163L72.0131 34.9014Z" fill="#283A97"></path>
                                <path d="M102.27 23.7007C102.27 20.6243 100.747 18.5484 96.9086 18.5484C95.0567 18.5484 93.2497 19.1159 91.7115 20.1464C91.0245 19.1458 89.7252 18.5484 87.5597 18.5484C85.7975 18.5783 84.08 19.1756 82.6613 20.236L82.1834 19.1607C82.0938 19.0114 81.9444 18.9068 81.7652 18.9068H80.4211C80.1523 18.9068 79.9432 19.1159 79.9432 19.3847V34.6326C79.9432 34.9014 80.1523 35.1105 80.4211 35.1105H83.1093C83.3781 35.1105 83.5872 34.9014 83.5872 34.6326V22.5657C84.6177 21.9534 85.7975 21.6249 86.9922 21.6249C88.4558 21.6249 89.2921 22.1625 89.2921 23.7157V34.6774C89.2921 34.9462 89.5012 35.1553 89.77 35.1553H92.4582C92.727 35.1553 92.9361 34.9462 92.9361 34.6774V22.5657C93.9516 21.9385 95.1463 21.6099 96.3411 21.6099C97.7748 21.6099 98.641 22.1476 98.641 23.7007V34.6625C98.641 34.9313 98.85 35.1404 99.1189 35.1404H101.807C102.076 35.1404 102.285 34.9313 102.285 34.6625L102.27 23.7007Z" fill="#283A97"></path>
                                <path d="M110.573 33.856C112.097 34.9761 113.934 35.5735 115.83 35.5436C120.565 35.5436 122.312 32.3626 122.312 27.046C122.312 21.7294 120.565 18.5484 115.83 18.5484C114.292 18.5633 112.784 18.9964 111.484 19.8178V14.9044C111.484 14.6356 111.275 14.4265 111.007 14.4265H108.318C108.05 14.4265 107.841 14.6356 107.841 14.9044V34.6625C107.841 34.9313 108.05 35.1404 108.318 35.1404H109.662C109.842 35.1404 109.991 35.0508 110.081 34.9014L110.573 33.856ZM114.979 32.4522C113.754 32.4522 112.545 32.1386 111.484 31.5113V22.5657C112.545 21.9534 113.754 21.6248 114.979 21.6248C118.16 21.6248 118.638 24.0591 118.638 27.0311C118.638 30.003 118.16 32.4522 114.979 32.4522Z" fill="#283A97"></path>
                                <path d="M135.738 21.7294C135.32 21.6697 134.901 21.6398 134.468 21.6547C133.02 21.595 131.586 21.9385 130.317 22.6254V34.6625C130.317 34.9313 130.108 35.1404 129.839 35.1404H127.151C126.882 35.1404 126.673 34.9313 126.673 34.6625V19.4146C126.673 19.1458 126.882 18.9367 127.151 18.9367H128.495C128.674 18.9367 128.823 19.0263 128.913 19.1756L129.391 20.2509C130.869 19.1308 132.676 18.5335 134.528 18.5633C134.946 18.5633 135.379 18.5932 135.798 18.6679C136.051 18.6679 136.246 19.0711 136.246 19.325V21.2664C136.246 21.5352 136.036 21.7443 135.768 21.7443L135.738 21.7294Z" fill="#283A97"></path>
                                <path d="M145.027 27.6583C143.429 27.8525 142.458 28.4648 142.458 30.1523C142.458 31.3919 142.996 32.5568 144.952 32.5568C146.192 32.5717 147.401 32.1983 148.417 31.4815V27.285L145.027 27.6583ZM149.313 33.856C147.924 34.9463 146.207 35.5436 144.429 35.5436C140.248 35.5436 138.859 32.9451 138.859 30.3465C138.859 26.8369 141.129 25.3584 144.788 25.0598L148.432 24.776V23.9696C148.432 22.3118 147.655 21.6697 145.251 21.6697C143.743 21.6697 142.249 21.9236 140.83 22.4015C140.786 22.4164 140.726 22.4164 140.681 22.4015C140.412 22.4015 140.203 22.1924 140.203 21.9236V19.773C140.203 19.5639 140.323 19.3847 140.517 19.3101C142.13 18.7724 143.817 18.5036 145.52 18.5036C150.836 18.5036 152.061 20.8334 152.061 24.2832V34.6326C152.061 34.9014 151.852 35.1105 151.583 35.1105H150.239C150.06 35.1105 149.91 35.0209 149.821 34.8716L149.313 33.856Z" fill="#283A97"></path>
                                <path d="M167.802 31.81C167.846 31.81 167.906 31.81 167.951 31.81C168.22 31.81 168.429 32.0191 168.429 32.2879V34.4384C168.429 34.6326 168.309 34.8118 168.13 34.8865C166.801 35.3644 165.382 35.6033 163.964 35.5734C158.214 35.5734 156.452 32.1386 156.452 27.0758C156.452 22.0131 158.214 18.5782 163.964 18.5782C165.367 18.5484 166.786 18.7574 168.115 19.2353C168.294 19.31 168.414 19.4892 168.414 19.6834V21.8488C168.414 22.1177 168.205 22.3267 167.936 22.3267C167.876 22.3417 167.832 22.3417 167.772 22.3267C166.607 21.9534 165.382 21.7742 164.158 21.7891C161.007 21.7891 160.096 23.9396 160.096 27.0758C160.096 30.212 161.007 32.3626 164.158 32.3626C165.382 32.3775 166.607 32.1983 167.772 31.8249" fill="#283A97"></path>
                            </svg>
                        </div>
                        <div class="area area-2">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[0]?.key}" .layoutColumns=${this.layout?.columnSpan}></umb-block-grid-entries>
                        </div>
                        <div class="area area-3">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[1]?.key}" .layoutColumns=${this.layout?.columnSpan}></umb-block-grid-entries>
                        </div>
                        <div class="area area-4">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[2]?.key}" .layoutColumns=${this.layout?.columnSpan}></umb-block-grid-entries>
                        </div>
                        <div class="area area-5">
                            <umb-block-grid-entries .areaKey="${this.layout?.areas?.[3]?.key}" .layoutColumns=${this.layout?.columnSpan}></umb-block-grid-entries>
                        </div>
                    </div>
                </figure>
            </fieldset>
        `;
    }

    static styles = [
        commonStyles,
        css`
            fieldset {
                background: #283a97;
                padding: 15px 15px 20px 15px;
            }
            
            .logo path {
                fill: white;
            }

            #grid {
                display: grid;
                grid-column-gap: 10px;
                grid-template-columns: repeat(5, 1fr);
            }

            .area {
                min-height: 100px;
            }
        `,
    ];
    
}
export default FooterLayoutBlockCustomView;

declare global {
    interface HTMLElementTagNameMap {
        'footer-layout-block-custom-view': FooterLayoutBlockCustomView;
    }
}
3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.