Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Marc Deschenes 5 posts 76 karma points
    Nov 21, 2021 @ 03:31
    Marc Deschenes
    0

    Nested block list for grids, and creating block models for api.editBlock ?

    Hey all!

    We have been evaluating different ways we could use the Block List editor, but have hit a snag and were wondering if anyone has experimented with complex grid layouts.

    So the abstract, we have 4 typical levels of nesting

    Section -> Row -> Column -> Components (buttons, image, cards, etc)

    We've experimented with two approaches.

    1) Setting individual Angular Views for each component, that way we have "block" model that gets created, and is available in the scope of each. Then each angular view does a bit of styling (grid classes and such) and loops on child blocks, calling

    <umb-property-editor model="property"></umb-property-editor>
    

    However, we quickly realized it would be rather difficult to style this properly, since the DOM is littered with a great deal of additional hierarchy from this directive. Several extra divs each level. Perhaps we missed something, but for Bootstrap 5 and other design systems, it would require a fairly strict div/class structure. But, on the flip side you do get the ability to open Content/Settings Drawer, as well as reorder them directly inline.

    2) One large Angular View assigned only to the top-most block (Section). This is pretty awesome, we have this looking really nice and it's pretty sweet to see grid sizing/alignment/spacing all work nicely. Here's a ballpark of what that code looks like, trimmed way down for brevity

    <section type="button" ng-controller="section.controller as vm" ng-click="api.editBlock(block, block.hideContentInOverlay, index, parentForm)">
        <!--Container-->
        <div class="container {{getContainerClasses(block.settingsData)}}" ng-attr-id="{{block.settingsData.sectionId}}">
            <!--Row-->
            <div class="row {{getRowClasses(row)}}"
                 ng-repeat="row in block.data.elements.layout['Umbraco.BlockList']"
                 ng-init="row.settings = getBlockSettings(block.data.elements, row);  
                          row.content = getBlockContent(block.data.elements, row)">
                <!-- Column -->
                <div class="col {{getColumnClasses(col)}}"
                     ng-repeat="col in row.content.elements.layout['Umbraco.BlockList']"
                     ng-style="{{getBackground(col)}}"
                     ng-init="col.settings = getBlockSettings(row.content.elements, col);
                              col.content = getBlockContent(row.content.elements, col)">
    
                    <!-- Components -->
                    <div ng-repeat="component in col.content.elements.layout['Umbraco.BlockList']"
                         ng-init="component.settings = getBlockSettings(col.content.elements, component);
                                  component.content = getBlockContent(col.content.elements, component)">
    
                        <!-- Button -->
                        <a ng-if="component.content.contentTypeKey === '6f7bdb10-c764-4278-aa15-8df95d069ddc'"
                           href="{{component.content.href}}"
                           class="btn {{getButtonClasses(component)}}">{{component.content.label}}</a>
    
                        <!-- Rich Text Editor -->
                        <div ng-if="component.content.contentTypeKey === '6965c527-0b47-4caf-91eb-16d9d497298b'"
                             ng-bind-html="component.content.content"></div>
    
                        <!-- Components that have not been defined yet -->
                        <div ng-if="getComponentName(component.content.contentTypeKey) === ''"
                             style="padding: 20px; background: #aa0000; border-radius: 4px;">
                            <div ng-if="true"><h3 style="color: white">Undefined Component - {{component.content.contentTypeKey}}</h3></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
    

    Bit monolithic at the moment since it's just a proof of concept, but it renders fantastic, and the power is vast :) However, we have a few questions/issues:

    1) How do we raise the Edit Content/Settings infinity drawer for child blocks? This is of course easy on the root scope, since the "block" model has both editBlock() and editSettings(), which we did find here

    It's a bit unclear how this scope level "block" model is constructed, and we're just curious if anyone has worked with this before?

    2) If so, would we need to create our own "block" model for each child element? Or is there an easier way to raise the Editor Drawer/Panel? Right now we're just looping on the raw JSON data, and editBlock() is just assigned on the top element. So that requires us to Click the block, then drill down through Row->Column->Component through infinity panels. Would much rather attach edit block calls on each child element (on an icon or something to avoid click bubbling).

    3) This sounds like a tall order, but would nested block sortable/ordering be possible in this situation? I assume more nested click event issues, but we could attach to a button/icon to reorder. Is it just a matter of reordering "layout" JSON branches, or is there anything else magical happening we should know about? Layout seems to infer the order, so is it just a matter of controlling that branch? Could we simply create up/down arrows as a last resort and shuffle layout json branches around?

    The block model available at the root scope does have the element alias, so for now we're just using contentTypeKey to figure out which component to render. I left a few examples in there if it helps anyone create something similar! Button/Rich Text Editor/DefaultUndefined. But an actual $scope.block model for each child element would be great, since it contains the actual Element Alias, so we could create angular directives around them.

    Thanks in advance to any brave takers :)

    -Marc

Please Sign in or register to post replies

Write your reply to:

Draft