Ensures that FormController hierarchy is maintained with infinite editors
This commit is contained in:
@@ -137,7 +137,7 @@
|
||||
// This directive allows for us to run a custom $compile for the view within the repeater which allows
|
||||
// us to maintain a $scope hierarchy with the rendered view based on the $scope that initiated the
|
||||
// infinite editing. The retain the $scope hiearchy a special $parentScope property is passed in to the model.
|
||||
function EditorRepeaterDirective($http, $templateCache, $compile) {
|
||||
function EditorRepeaterDirective($http, $templateCache, $compile, angularHelper) {
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
var editor = scope && scope.$parent ? scope.$parent.model : null;
|
||||
@@ -159,14 +159,24 @@
|
||||
});
|
||||
|
||||
// NOTE: the 'model' name here directly affects the naming convention used in infinite editors, this why you access the model
|
||||
// like $scope.model.If this is changed, everything breaks.This is because we are entirely reliant upon ng - include and inheriting $scopes.
|
||||
// like $scope.model.If this is changed, everything breaks.This is because we are entirely reliant upon ng-include and inheriting $scopes.
|
||||
// by default without a $parentScope used for infinite editing the 'model' propety will be set because the view creates the scopes in
|
||||
// ng-repeat by ng-repeat="model in editors"
|
||||
templateScope.model = editor;
|
||||
|
||||
element.html(response.data);
|
||||
|
||||
element.show();
|
||||
$compile(element.contents())(templateScope);
|
||||
|
||||
// if a parentForm is supplied then we can link them but to do that we need to inject a top level form
|
||||
if (editor.$parentForm) {
|
||||
element.html("<ng-form name='infiniteEditorForm'>" + response.data + "</ng-form>");
|
||||
}
|
||||
|
||||
$compile(element)(templateScope);
|
||||
|
||||
// if a parentForm is supplied then we can link them
|
||||
if (editor.$parentForm) {
|
||||
editor.$parentForm.$addControl(templateScope.infiniteEditorForm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ Opens an overlay to show a custom YSOD. </br>
|
||||
templateScope.model = scope.model;
|
||||
element.html(response.data);
|
||||
element.show();
|
||||
$compile(element.contents())(templateScope);
|
||||
$compile(element)(templateScope);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<umb-block-list-property-editor property-form="propertyForm" model="model"/>
|
||||
<umb-block-list-property-editor model="model"/>
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
<ng-form name="blockRowForm" val-server-match="{ 'contains' : block.content.key }">
|
||||
<div class="blockelement-inlineblock-editor"
|
||||
ng-controller="Umbraco.PropertyEditors.BlockEditor.InlineBlockEditor as vm"
|
||||
ng-class="{ '--error': blockRowForm.$invalid }">
|
||||
<button type="button" class="btn-reset umb-outline blockelement__draggable-element"
|
||||
ng-click="vm.openBlock(block)"
|
||||
ng-focus="block.focus">
|
||||
<span class="caret"></span>
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
</button>
|
||||
<div class="blockelement-inlineblock-editor__inner" ng-class="{'--singleGroup':block.content.variants[0].tabs.length === 1}" ng-if="block.active === true">
|
||||
<umb-element-editor-content model="block.content"></umb-element-editor-content>
|
||||
</div>
|
||||
<div class="blockelement-inlineblock-editor"
|
||||
ng-controller="Umbraco.PropertyEditors.BlockEditor.InlineBlockEditor as vm"
|
||||
ng-class="{ '--error': blockRowForm.$invalid }">
|
||||
<button type="button" class="btn-reset umb-outline blockelement__draggable-element"
|
||||
ng-click="vm.openBlock(block)"
|
||||
ng-focus="block.focus">
|
||||
<span class="caret"></span>
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
</button>
|
||||
<div class="blockelement-inlineblock-editor__inner" ng-class="{'--singleGroup':block.content.variants[0].tabs.length === 1}" ng-if="block.active === true">
|
||||
<umb-element-editor-content model="block.content"></umb-element-editor-content>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<ng-form name="blockRowForm" val-server-match="{ 'contains' : block.content.key }">
|
||||
<button type="button" class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element"
|
||||
ng-click="api.editBlock(block, block.hideContentInOverlay, index)"
|
||||
ng-focus="block.focus"
|
||||
ng-class="{ '--active': block.active, '--error': blockRowForm.$invalid }"
|
||||
val-server-property-class="">
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
</button>
|
||||
</ng-form>
|
||||
<button type="button" class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element"
|
||||
ng-click="api.editBlock(block, block.hideContentInOverlay, index, parentForm)"
|
||||
ng-focus="block.focus"
|
||||
ng-class="{ '--active': block.active, '--error': blockRowForm.$invalid }"
|
||||
val-server-property-class="">
|
||||
<i class="icon {{block.content.icon}}"></i>
|
||||
<span>{{block.label}}</span>
|
||||
</button>
|
||||
|
||||
@@ -18,49 +18,10 @@
|
||||
<div class="__plus" ng-style="{'left':inlineCreateButtonCtrl.plusPosX}">+</div>
|
||||
</button>
|
||||
|
||||
<div class="umb-block-list__block" ng-class="{'--active':layout.$block.active}">
|
||||
|
||||
<umb-block-list-scoped-block
|
||||
ng-if="layout.$block.config.stylesheet"
|
||||
class="umb-block-list__block--content blockelement__draggable-element"
|
||||
view="{{layout.$block.view}}"
|
||||
stylesheet="/{{::layout.$block.config.stylesheet}}"
|
||||
api="vm.blockEditorApi"
|
||||
block="layout.$block"
|
||||
index="$index">
|
||||
</umb-block-list-scoped-block>
|
||||
<umb-block-list-block
|
||||
ng-if="!layout.$block.config.stylesheet"
|
||||
class="umb-block-list__block--content"
|
||||
view="{{layout.$block.view}}"
|
||||
api="vm.blockEditorApi"
|
||||
block="layout.$block"
|
||||
index="$index">
|
||||
</umb-block-list-block>
|
||||
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset umb-outline action --settings" localize="title" title="actions_editSettings"
|
||||
ng-click="vm.blockEditorApi.openSettingsForBlock(layout.$block, $index);"
|
||||
ng-if="layout.$block.showSettings === true">
|
||||
<i class="icon icon-settings" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_settings">Settings</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy" ng-click="vm.blockEditorApi.copyBlock(layout.$block);" ng-if="layout.$block.showCopy === true">
|
||||
<i class="icon icon-documents" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_copy">Copy</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --delete" localize="title" title="actions_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(layout.$block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<umb-block-list-row block-editor-api="vm.blockEditorApi"
|
||||
layout="layout"
|
||||
index="$index">
|
||||
</umb-block-list-row>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<ng-form name="vm.blockRowForm" val-server-match="{ 'contains' : vm.layout.$block.content.key }">
|
||||
<div class="umb-block-list__block" ng-class="{'--active':vm.layout.$block.active}">
|
||||
|
||||
<umb-block-list-scoped-block ng-if="vm.layout.$block.config.stylesheet"
|
||||
class="umb-block-list__block--content blockelement__draggable-element"
|
||||
view="{{vm.layout.$block.view}}"
|
||||
stylesheet="/{{::vm.layout.$block.config.stylesheet}}"
|
||||
api="vm.blockEditorApi"
|
||||
block="vm.layout.$block"
|
||||
index="vm.index"
|
||||
parent-form="vm.blockRowForm">
|
||||
</umb-block-list-scoped-block>
|
||||
<umb-block-list-block ng-if="!vm.layout.$block.config.stylesheet"
|
||||
class="umb-block-list__block--content"
|
||||
view="{{vm.layout.$block.view}}"
|
||||
api="vm.blockEditorApi"
|
||||
block="vm.layout.$block"
|
||||
index="vm.index"
|
||||
parent-form="vm.blockRowForm">
|
||||
</umb-block-list-block>
|
||||
|
||||
<div class="umb-block-list__block--actions">
|
||||
<button type="button" class="btn-reset umb-outline action --settings" localize="title" title="actions_editSettings"
|
||||
ng-click="vm.blockEditorApi.openSettingsForBlock(vm.layout.$block, vm.index);"
|
||||
ng-if="vm.layout.$block.showSettings === true">
|
||||
<i class="icon icon-settings" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_settings">Settings</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --copy" localize="title" title="actions_copy" ng-click="vm.blockEditorApi.copyBlock(vm.layout.$block);" ng-if="vm.layout.$block.showCopy === true">
|
||||
<i class="icon icon-documents" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_copy">Copy</localize>
|
||||
</span>
|
||||
</button>
|
||||
<button type="button" class="btn-reset umb-outline action --delete" localize="title" title="actions_delete" ng-click="vm.blockEditorApi.requestDeleteBlock(vm.layout.$block);">
|
||||
<i class="icon icon-trash" aria-hidden="true"></i>
|
||||
<span class="sr-only">
|
||||
<localize key="general_delete">Delete</localize>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
@@ -17,10 +17,10 @@
|
||||
controller: BlockListController,
|
||||
controllerAs: "vm",
|
||||
bindings: {
|
||||
model: "=",
|
||||
propertyForm: "="
|
||||
model: "="
|
||||
},
|
||||
require: {
|
||||
propertyForm: "^form",
|
||||
umbProperty: "?^umbProperty",
|
||||
umbVariantContent: '?^^umbVariantContent',
|
||||
umbVariantContentEditors: '?^^umbVariantContentEditors',
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
function BlockListController($scope, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager) {
|
||||
function BlockListController($scope, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager, angularHelper) {
|
||||
|
||||
var unsubscribe = [];
|
||||
var modelObject;
|
||||
@@ -65,6 +65,16 @@
|
||||
|
||||
vm.$onInit = function() {
|
||||
|
||||
if (!vm.umbVariantContent) {
|
||||
// not found, then fallback to searching the scope chain, this may be needed when DOM inheritance isn't maintained but scope
|
||||
// inheritance is (i.e.infinite editing)
|
||||
var found = angularHelper.traverseScopeChain($scope, s => s && s.vm && s.vm.constructor.name === "umbVariantContentController");
|
||||
vm.umbVariantContent = found ? found.vm : null;
|
||||
if (!vm.umbVariantContent) {
|
||||
throw "Could not find umbVariantContent in the $scope chain";
|
||||
}
|
||||
}
|
||||
|
||||
// set the onValueChanged callback, this will tell us if the block list model changed on the server
|
||||
// once the data is submitted. If so we need to re-initialize
|
||||
vm.model.onValueChanged = onServerValueChanged;
|
||||
@@ -258,7 +268,7 @@
|
||||
blockObject.active = true;
|
||||
}
|
||||
|
||||
function editBlock(blockObject, openSettings, blockIndex) {
|
||||
function editBlock(blockObject, openSettings, blockIndex, parentForm) {
|
||||
|
||||
// this must be set
|
||||
if (blockIndex === undefined) {
|
||||
@@ -289,6 +299,7 @@
|
||||
|
||||
var blockEditorModel = {
|
||||
$parentScope: $scope, // pass in a $parentScope, this maintains the scope inheritance in infinite editing
|
||||
$parentForm: parentForm || vm.propertyForm, // pass in a $parentForm, this maintains the FormController hierarchy with the infinite editing view (if it contains a form)
|
||||
hideContent: blockObject.hideContentInOverlay,
|
||||
openSettings: openSettings === true,
|
||||
liveEditing: liveEditing,
|
||||
@@ -345,6 +356,8 @@
|
||||
|
||||
var amountOfAvailableTypes = vm.availableBlockTypes.length;
|
||||
var blockPickerModel = {
|
||||
$parentScope: $scope, // pass in a $parentScope, this maintains the scope inheritance in infinite editing
|
||||
$parentForm: vm.propertyForm, // pass in a $parentForm, this maintains the FormController hierarchy with the infinite editing view (if it contains a form)
|
||||
availableItems: vm.availableBlockTypes,
|
||||
title: vm.labels.grid_addElement,
|
||||
orderBy: "$index",
|
||||
@@ -378,7 +391,7 @@
|
||||
if (inlineEditing === true) {
|
||||
activateBlock(vm.layout[createIndex].$block);
|
||||
} else if (inlineEditing === false && vm.layout[createIndex].$block.hideContentInOverlay !== true) {
|
||||
editBlock(vm.layout[createIndex].$block, false, createIndex);
|
||||
editBlock(vm.layout[createIndex].$block, false, createIndex, blockPickerModel.$parentForm);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -521,6 +534,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: We'll need to pass in a parentForm here too
|
||||
function openSettingsForBlock(block, blockIndex) {
|
||||
editBlock(block, true, blockIndex);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
view: "@",
|
||||
block: "=",
|
||||
api: "<",
|
||||
index: "<"
|
||||
index: "<",
|
||||
parentForm: "<"
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -32,6 +33,7 @@
|
||||
$scope.block = model.block;
|
||||
$scope.api = model.api;
|
||||
$scope.index = model.index;
|
||||
$scope.parentForm = model.parentForm;
|
||||
};
|
||||
|
||||
// We need to watch for changes on primitive types and upate the $scope values.
|
||||
@@ -0,0 +1,34 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbBlockListRow
|
||||
* @description
|
||||
* renders each row for the block list editor
|
||||
*/
|
||||
|
||||
angular
|
||||
.module("umbraco")
|
||||
.component("umbBlockListRow", {
|
||||
templateUrl: 'views/propertyeditors/blocklist/umb-block-list-row.html',
|
||||
controller: BlockListRowController,
|
||||
controllerAs: "vm",
|
||||
bindings: {
|
||||
blockEditorApi: "<",
|
||||
layout: "<",
|
||||
index: "<"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function BlockListRowController($scope) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
vm.$onInit = function () {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -20,7 +20,8 @@
|
||||
view: "@",
|
||||
block: "=",
|
||||
api: "<",
|
||||
index: "<"
|
||||
index: "<",
|
||||
parentForm: "<"
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -34,6 +35,7 @@
|
||||
$scope.block = model.block;
|
||||
$scope.api = model.api;
|
||||
$scope.index = model.index;
|
||||
$scope.parentForm = model.parentForm;
|
||||
|
||||
var shadowRoot = $element[0].attachShadow({mode:'open'});
|
||||
shadowRoot.innerHTML = `
|
||||
Reference in New Issue
Block a user