v10: make block editors supports stateful label expressions (#12909)
* mark ncNodeName as stateful allowing it to update the node name asynchronously and implement several checks for caching and fallthroughs * ensure that the blocklist block component watches and updates stuff on the blockObject * add $interpolate to the blockList Property Editor to interpolate the label with the saved state * replace static label with the blockHtmlCompile directive to ensure labels are updated dynamically * add failsafe in case block is not instantiated * replace manual udi separation with the parse function from the udiParser service * simplify watching, to avoid overwritting data object. * virtual block label rendering * destroy label scope * add extra information for label doc * revert previously used functions and add deprecation notices to them * remove getBlockLabel, as it's not being used or publicly available. Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
This commit is contained in:
@@ -3,67 +3,78 @@
|
||||
|
||||
// Cache for node names so we don't make a ton of requests
|
||||
var ncNodeNameCache = {
|
||||
id: "",
|
||||
keys: {}
|
||||
id: "",
|
||||
keys: {}
|
||||
};
|
||||
|
||||
angular.module("umbraco.filters").filter("ncNodeName", function (editorState, entityResource) {
|
||||
angular.module("umbraco.filters").filter("ncNodeName", function (editorState, entityResource, udiParser) {
|
||||
|
||||
function formatLabel(firstNodeName, totalNodes) {
|
||||
return totalNodes <= 1
|
||||
? firstNodeName
|
||||
// If there is more than one item selected, append the additional number of items selected to hint that
|
||||
: firstNodeName + " (+" + (totalNodes - 1) + ")";
|
||||
function formatLabel(firstNodeName, totalNodes) {
|
||||
return totalNodes <= 1
|
||||
? firstNodeName
|
||||
// If there is more than one item selected, append the additional number of items selected to hint that
|
||||
: firstNodeName + " (+" + (totalNodes - 1) + ")";
|
||||
}
|
||||
|
||||
nodeNameFilter.$stateful = true;
|
||||
function nodeNameFilter(input) {
|
||||
|
||||
// Check we have a value at all
|
||||
if (typeof input === 'undefined' || input === "" || input.toString() === "0" || input === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return function (input) {
|
||||
var currentNode = editorState.getCurrent();
|
||||
|
||||
// Check we have a value at all
|
||||
if (input === "" || input.toString() === "0") {
|
||||
return "";
|
||||
}
|
||||
// Ensure a unique cache per editor instance
|
||||
var key = "ncNodeName_" + currentNode.key;
|
||||
if (ncNodeNameCache.id !== key) {
|
||||
ncNodeNameCache.id = key;
|
||||
ncNodeNameCache.keys = {};
|
||||
}
|
||||
|
||||
var currentNode = editorState.getCurrent();
|
||||
// MNTP values are comma separated IDs. We'll only fetch the first one for the NC header.
|
||||
var ids = input.split(',');
|
||||
var lookupId = ids[0];
|
||||
var serviceInvoked = false;
|
||||
|
||||
// Ensure a unique cache per editor instance
|
||||
var key = "ncNodeName_" + currentNode.key;
|
||||
if (ncNodeNameCache.id !== key) {
|
||||
ncNodeNameCache.id = key;
|
||||
ncNodeNameCache.keys = {};
|
||||
}
|
||||
// See if there is a value in the cache and use that
|
||||
if (ncNodeNameCache.keys[lookupId]) {
|
||||
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
|
||||
}
|
||||
|
||||
// MNTP values are comma separated IDs. We'll only fetch the first one for the NC header.
|
||||
var ids = input.split(',');
|
||||
var lookupId = ids[0];
|
||||
// No value, so go fetch one
|
||||
// We'll put a temp value in the cache though so we don't
|
||||
// make a load of requests while we wait for a response
|
||||
ncNodeNameCache.keys[lookupId] = "Loading...";
|
||||
|
||||
// See if there is a value in the cache and use that
|
||||
if (ncNodeNameCache.keys[lookupId]) {
|
||||
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
|
||||
}
|
||||
// If the service has already been invoked, don't do it again
|
||||
if (serviceInvoked) {
|
||||
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
|
||||
}
|
||||
|
||||
// No value, so go fetch one
|
||||
// We'll put a temp value in the cache though so we don't
|
||||
// make a load of requests while we wait for a response
|
||||
ncNodeNameCache.keys[lookupId] = "Loading...";
|
||||
serviceInvoked = true;
|
||||
|
||||
var type = lookupId.indexOf("umb://media/") === 0
|
||||
? "Media"
|
||||
: lookupId.indexOf("umb://member/") === 0
|
||||
? "Member"
|
||||
: "Document";
|
||||
entityResource.getById(lookupId, type)
|
||||
.then(
|
||||
function (ent) {
|
||||
ncNodeNameCache.keys[lookupId] = ent.name;
|
||||
}
|
||||
);
|
||||
var udi = udiParser.parse(lookupId);
|
||||
|
||||
// Return the current value for now
|
||||
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
|
||||
};
|
||||
if (udi) {
|
||||
entityResource.getById(udi.value, udi.entityType).then(function (ent) {
|
||||
ncNodeNameCache.keys[lookupId] = ent.name;
|
||||
}).catch(function () {
|
||||
ncNodeNameCache.keys[lookupId] = "Error: Could not load";
|
||||
});
|
||||
} else {
|
||||
ncNodeNameCache.keys[lookupId] = "Error: Not a UDI";
|
||||
}
|
||||
|
||||
// Return the current value for now
|
||||
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
|
||||
}
|
||||
|
||||
return nodeNameFilter;
|
||||
|
||||
}).filter("ncRichText", function () {
|
||||
return function(input) {
|
||||
return $("<div/>").html(input).text();
|
||||
};
|
||||
return function (input) {
|
||||
return $("<div/>").html(input).text();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper, clipboardService, notificationsService) {
|
||||
function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper, clipboardService, notificationsService, $compile) {
|
||||
|
||||
/**
|
||||
* Simple mapping from property model content entry to editing model,
|
||||
@@ -62,8 +62,8 @@
|
||||
/**
|
||||
* Map property values from an ElementModel to another ElementModel.
|
||||
* Used to tricker watchers for synchronization.
|
||||
* @param {Object} fromModel ElementModel to recive property values from.
|
||||
* @param {Object} toModel ElementModel to recive property values from.
|
||||
* @param {Object} fromModel ElementModel to receive property values from.
|
||||
* @param {Object} toModel ElementModel to receive property values from.
|
||||
*/
|
||||
function mapElementValues(fromModel, toModel) {
|
||||
if (!fromModel || !fromModel.variants) {
|
||||
@@ -97,40 +97,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate label for Block, uses either the labelInterpolator or falls back to the contentTypeName.
|
||||
* @param {Object} blockObject BlockObject to receive data values from.
|
||||
*/
|
||||
function getBlockLabel(blockObject) {
|
||||
if (blockObject.labelInterpolator !== undefined) {
|
||||
// blockobject.content may be null if the block is no longer allowed,
|
||||
// so try and fall back to the label in the config,
|
||||
// if that too is null, there's not much we can do, so just default to empty string.
|
||||
var contentTypeName;
|
||||
if(blockObject.content != null){
|
||||
contentTypeName = blockObject.content.contentTypeName;
|
||||
}
|
||||
else if(blockObject.config != null && blockObject.config.label != null){
|
||||
contentTypeName = blockObject.config.label;
|
||||
}
|
||||
else {
|
||||
contentTypeName = "";
|
||||
}
|
||||
|
||||
var labelVars = Object.assign({
|
||||
"$contentTypeName": contentTypeName,
|
||||
"$settings": blockObject.settingsData || {},
|
||||
"$layout": blockObject.layout || {},
|
||||
"$index": (blockObject.index || 0)+1
|
||||
}, blockObject.data);
|
||||
var label = blockObject.labelInterpolator(labelVars);
|
||||
if (label) {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
return blockObject.content.contentTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to add watchers on all properties in a content or settings model
|
||||
*/
|
||||
@@ -161,10 +127,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (blockObject.__watchers.length === 0) {
|
||||
// If no watcher where created, it means we have no properties to watch. This means that nothing will activate our generate the label, since its only triggered by watchers.
|
||||
blockObject.updateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,8 +138,6 @@
|
||||
|
||||
// sync data:
|
||||
prop.value = blockObject.data[prop.alias];
|
||||
|
||||
blockObject.updateLabel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,8 +163,6 @@
|
||||
// sync data:
|
||||
blockObject.data[prop.alias] = prop.value;
|
||||
}
|
||||
|
||||
blockObject.updateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,11 +280,11 @@
|
||||
* @param {object} propertyModelValue data object of the property editor, usually model.value.
|
||||
* @param {string} propertyEditorAlias alias of the property.
|
||||
* @param {object} blockConfigurations block configurations.
|
||||
* @param {angular-scope} scopeOfExistance A local angularJS scope that exists as long as the data exists.
|
||||
* @param {angular-scope} scopeOfExistence A local angularJS scope that exists as long as the data exists.
|
||||
* @param {angular-scope} propertyEditorScope A local angularJS scope that represents the property editors scope.
|
||||
* @returns {BlockEditorModelObject} A instance of BlockEditorModelObject.
|
||||
*/
|
||||
function BlockEditorModelObject(propertyModelValue, propertyEditorAlias, blockConfigurations, scopeOfExistance, propertyEditorScope) {
|
||||
function BlockEditorModelObject(propertyModelValue, propertyEditorAlias, blockConfigurations, scopeOfExistence, propertyEditorScope) {
|
||||
|
||||
if (!propertyModelValue) {
|
||||
throw new Error("propertyModelValue cannot be undefined, to ensure we keep the binding to the angular model we need minimum an empty object.");
|
||||
@@ -358,8 +316,8 @@
|
||||
});
|
||||
|
||||
this.scaffolds = [];
|
||||
|
||||
this.isolatedScope = scopeOfExistance.$new(true);
|
||||
this.__scopeOfExistence = scopeOfExistence;
|
||||
this.isolatedScope = scopeOfExistence.$new(true);
|
||||
this.isolatedScope.blockObjects = {};
|
||||
|
||||
this.__watchers.push(this.isolatedScope.$on("$destroy", this.destroy.bind(this)));
|
||||
@@ -397,7 +355,7 @@
|
||||
* @name getBlockConfiguration
|
||||
* @methodOf umbraco.services.blockEditorModelObject
|
||||
* @description Get block configuration object for a given contentElementTypeKey.
|
||||
* @param {string} key contentElementTypeKey to recive the configuration model for.
|
||||
* @param {string} key contentElementTypeKey to receive the configuration model for.
|
||||
* @returns {Object | null} Configuration model for the that specific block. Or ´null´ if the contentElementTypeKey isnt available in the current block configurations.
|
||||
*/
|
||||
getBlockConfiguration: function (key) {
|
||||
@@ -477,7 +435,7 @@
|
||||
* @ngdoc method
|
||||
* @name getAvailableBlocksForBlockPicker
|
||||
* @methodOf umbraco.services.blockEditorModelObject
|
||||
* @description Retrieve a list of available blocks, the list containing object with the confirugation model(blockConfigModel) and the element type model(elementTypeModel).
|
||||
* @description Retrieve a list of available blocks, the list containing object with the configuration model(blockConfigModel) and the element type model(elementTypeModel).
|
||||
* The purpose of this data is to provide it for the Block Picker.
|
||||
* @return {Array} array of objects representing available blocks, each object containing properties blockConfigModel and elementTypeModel.
|
||||
*/
|
||||
@@ -503,7 +461,7 @@
|
||||
* @name getScaffoldFromKey
|
||||
* @methodOf umbraco.services.blockEditorModelObject
|
||||
* @description Get scaffold model for a given contentTypeKey.
|
||||
* @param {string} key contentTypeKey to recive the scaffold model for.
|
||||
* @param {string} key contentTypeKey to receive the scaffold model for.
|
||||
* @returns {Object | null} Scaffold model for the that content type. Or null if the scaffolding model dosnt exist in this context.
|
||||
*/
|
||||
getScaffoldFromKey: function (contentTypeKey) {
|
||||
@@ -515,7 +473,7 @@
|
||||
* @name getScaffoldFromAlias
|
||||
* @methodOf umbraco.services.blockEditorModelObject
|
||||
* @description Get scaffold model for a given contentTypeAlias, used by clipboardService.
|
||||
* @param {string} alias contentTypeAlias to recive the scaffold model for.
|
||||
* @param {string} alias contentTypeAlias to receive the scaffold model for.
|
||||
* @returns {Object | null} Scaffold model for the that content type. Or null if the scaffolding model dosnt exist in this context.
|
||||
*/
|
||||
getScaffoldFromAlias: function (contentTypeAlias) {
|
||||
@@ -535,8 +493,7 @@
|
||||
* - content {Object}: Content model, the content data in a ElementType model.
|
||||
* - settings {Object}: Settings model, the settings data in a ElementType model.
|
||||
* - config {Object}: A local deep copy of the block configuration model.
|
||||
* - label {string}: The label for this block.
|
||||
* - updateLabel {Method}: Method to trigger an update of the label for this block.
|
||||
* - label {string}: The compiled label for this block.
|
||||
* - data {Object}: A reference to the content data object from your property editor model.
|
||||
* - settingsData {Object}: A reference to the settings data object from your property editor model.
|
||||
* - layout {Object}: A reference to the layout entry from your property editor model.
|
||||
@@ -581,18 +538,12 @@
|
||||
blockObject.key = String.CreateGuid().replace(/-/g, "");
|
||||
blockObject.config = Utilities.copy(blockConfiguration);
|
||||
if (blockObject.config.label && blockObject.config.label !== "") {
|
||||
blockObject.labelInterpolator = $interpolate(blockObject.config.label);
|
||||
/**
|
||||
* @deprecated use blockObject.label instead
|
||||
*/
|
||||
blockObject.labelInterpolator = $interpolate(blockObject.config.label);
|
||||
}
|
||||
blockObject.__scope = this.isolatedScope;
|
||||
blockObject.updateLabel = _.debounce(
|
||||
function () {
|
||||
// Check wether scope still exists, maybe object was destoyed in these seconds.
|
||||
if (this.__scope) {
|
||||
this.label = getBlockLabel(this);
|
||||
this.__scope.$evalAsync();
|
||||
}
|
||||
}.bind(blockObject)
|
||||
, 10);
|
||||
|
||||
// make basics from scaffold
|
||||
if(contentScaffold !== null) {// We might not have contentScaffold
|
||||
@@ -655,6 +606,7 @@
|
||||
if (this.config.settingsElementTypeKey !== null) {
|
||||
mapElementValues(settings, this.settings);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
blockObject.sync = function () {
|
||||
@@ -667,7 +619,61 @@
|
||||
};
|
||||
|
||||
// first time instant update of label.
|
||||
blockObject.label = getBlockLabel(blockObject);
|
||||
blockObject.label = blockObject.content.contentTypeName;
|
||||
blockObject.index = 0;
|
||||
|
||||
if (blockObject.config.label && blockObject.config.label !== "") {
|
||||
var labelElement = $('<div></div>', { text: blockObject.config.label});
|
||||
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
blockObject.label = mutation.target.textContent;
|
||||
blockObject.__scope.$evalAsync();
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(labelElement[0], {characterData: true, subtree:true});
|
||||
|
||||
blockObject.__watchers.push(() => {
|
||||
observer.disconnect();
|
||||
})
|
||||
|
||||
blockObject.__labelScope = this.__scopeOfExistence.$new(true);
|
||||
blockObject.__renderLabel = function() {
|
||||
|
||||
var labelVars = {
|
||||
$contentTypeName: this.content.contentTypeName,
|
||||
$settings: this.settingsData || {},
|
||||
$layout: this.layout || {},
|
||||
$index: this.index + 1,
|
||||
... this.data
|
||||
};
|
||||
|
||||
this.__labelScope = Object.assign(this.__labelScope, labelVars);
|
||||
|
||||
$compile(labelElement.contents())(this.__labelScope);
|
||||
}.bind(blockObject)
|
||||
} else {
|
||||
blockObject.__renderLabel = function() {};
|
||||
}
|
||||
|
||||
blockObject.updateLabel = _.debounce(blockObject.__renderLabel, 10);
|
||||
|
||||
|
||||
// label rendering watchers:
|
||||
blockObject.__watchers.push(blockObject.__scope.$watchCollection(function () {
|
||||
return blockObject.data;
|
||||
}, blockObject.__renderLabel));
|
||||
blockObject.__watchers.push(blockObject.__scope.$watchCollection(function () {
|
||||
return blockObject.settingsData;
|
||||
}, blockObject.__renderLabel));
|
||||
blockObject.__watchers.push(blockObject.__scope.$watchCollection(function () {
|
||||
return blockObject.layout;
|
||||
}, blockObject.__renderLabel));
|
||||
blockObject.__watchers.push(blockObject.__scope.$watch(function () {
|
||||
return blockObject.index;
|
||||
}, blockObject.__renderLabel));
|
||||
|
||||
|
||||
// Add blockObject to our isolated scope to enable watching its values:
|
||||
this.isolatedScope.blockObjects["_" + blockObject.key] = blockObject;
|
||||
@@ -679,9 +685,8 @@
|
||||
this.__watchers.forEach(w => { w(); });
|
||||
delete this.__watchers;
|
||||
|
||||
// help carbage collector:
|
||||
// help garbage collector:
|
||||
delete this.config;
|
||||
|
||||
delete this.layout;
|
||||
delete this.data;
|
||||
delete this.settingsData;
|
||||
@@ -695,6 +700,11 @@
|
||||
// destroyed. If we do that here it breaks the scope chain and validation.
|
||||
delete this.__scope;
|
||||
|
||||
if(this.__labelScope) {
|
||||
this.__labelScope.$destroy();
|
||||
delete this.__labelScope;
|
||||
}
|
||||
|
||||
// removes this method, making it impossible to destroy again.
|
||||
delete this.destroy;
|
||||
|
||||
@@ -917,6 +927,7 @@
|
||||
delete this.scaffolds;
|
||||
this.isolatedScope.$destroy();
|
||||
delete this.isolatedScope;
|
||||
delete this.__scopeOfExistence;
|
||||
delete this.destroy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<button type="button" class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element"
|
||||
ng-click="block.edit()"
|
||||
ng-focus="block.focus"
|
||||
ng-class="{ '--active': block.active, '--error': parentForm.$invalid && valFormManager.isShowingValidation() }"
|
||||
val-server-property-class="">
|
||||
<umb-icon icon="{{block.content.icon}}" class="icon"></umb-icon>
|
||||
<span>{{block.label}}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-reset umb-outline blockelement-labelblock-editor blockelement__draggable-element"
|
||||
ng-click="block.edit()"
|
||||
ng-focus="block.focus"
|
||||
ng-class="{ '--active': block.active, '--error': parentForm.$invalid && valFormManager.isShowingValidation() }"
|
||||
val-server-property-class=""
|
||||
>
|
||||
<umb-icon icon="{{block.content.icon}}" class="icon"></umb-icon>
|
||||
<span>{{block.label}}</span>
|
||||
</button>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
function BlockListController($scope, $timeout, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager, angularHelper, eventsService, $attrs) {
|
||||
function BlockListController($scope, $timeout, $interpolate, editorService, clipboardService, localizationService, overlayService, blockEditorService, udiService, serverValidationManager, angularHelper, eventsService, $attrs) {
|
||||
|
||||
var unsubscribe = [];
|
||||
var modelObject;
|
||||
|
||||
@@ -1,85 +1,86 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbBlockListBlock
|
||||
* @description
|
||||
* The component to render the view for a block.
|
||||
* If a stylesheet is used then this uses a ShadowDom to make a scoped element.
|
||||
* This way the backoffice styling does not collide with the block style.
|
||||
*/
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbBlockListBlock
|
||||
* @description
|
||||
* The component to render the view for a block.
|
||||
* If a stylesheet is used then this uses a ShadowDom to make a scoped element.
|
||||
* This way the backoffice styling does not collide with the block style.
|
||||
*/
|
||||
|
||||
angular
|
||||
.module("umbraco")
|
||||
.component("umbBlockListBlock", {
|
||||
controller: BlockListBlockController,
|
||||
controllerAs: "model",
|
||||
bindings: {
|
||||
stylesheet: "@",
|
||||
view: "@",
|
||||
block: "=",
|
||||
api: "<",
|
||||
index: "<",
|
||||
parentForm: "<"
|
||||
},
|
||||
require: {
|
||||
valFormManager: "^^valFormManager"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
angular
|
||||
.module("umbraco")
|
||||
.component("umbBlockListBlock", {
|
||||
controller: BlockListBlockController,
|
||||
controllerAs: "model",
|
||||
bindings: {
|
||||
stylesheet: "@",
|
||||
view: "@",
|
||||
block: "=",
|
||||
api: "<",
|
||||
index: "<",
|
||||
parentForm: "<"
|
||||
},
|
||||
require: {
|
||||
valFormManager: "^^valFormManager"
|
||||
}
|
||||
}
|
||||
);
|
||||
function BlockListBlockController($scope, $compile, $element) {
|
||||
var model = this;
|
||||
|
||||
function BlockListBlockController($scope, $compile, $element) {
|
||||
var model = this;
|
||||
model.$onInit = function () {
|
||||
// This is ugly and is only necessary because we are not using components and instead
|
||||
// relying on ng-include. It is definitely possible to compile the contents
|
||||
// of the view into the DOM using $templateCache and $http instead of using
|
||||
// ng - include which means that the controllerAs flows directly to the view.
|
||||
// This would mean that any custom components would need to be updated instead of relying on $scope.
|
||||
// Guess we'll leave it for now but means all things need to be copied to the $scope and then all
|
||||
// primitives need to be watched.
|
||||
|
||||
model.$onInit = function () {
|
||||
// This is ugly and is only necessary because we are not using components and instead
|
||||
// relying on ng-include. It is definitely possible to compile the contents
|
||||
// of the view into the DOM using $templateCache and $http instead of using
|
||||
// ng - include which means that the controllerAs flows directly to the view.
|
||||
// This would mean that any custom components would need to be updated instead of relying on $scope.
|
||||
// Guess we'll leave it for now but means all things need to be copied to the $scope and then all
|
||||
// primitives need to be watched.
|
||||
// let the Block know about its form
|
||||
model.block.setParentForm(model.parentForm);
|
||||
|
||||
// let the Block know about its form
|
||||
model.block.setParentForm(model.parentForm);
|
||||
// let the Block know about the current index
|
||||
model.block.index = model.index;
|
||||
|
||||
// let the Block know about the current index
|
||||
model.block.index = model.index;
|
||||
$scope.block = model.block;
|
||||
$scope.api = model.api;
|
||||
$scope.index = model.index;
|
||||
$scope.parentForm = model.parentForm;
|
||||
$scope.valFormManager = model.valFormManager;
|
||||
|
||||
$scope.block = model.block;
|
||||
$scope.api = model.api;
|
||||
$scope.index = model.index;
|
||||
$scope.parentForm = model.parentForm;
|
||||
$scope.valFormManager = model.valFormManager;
|
||||
|
||||
if (model.stylesheet) {
|
||||
var shadowRoot = $element[0].attachShadow({ mode: 'open' });
|
||||
shadowRoot.innerHTML = `
|
||||
if (model.stylesheet) {
|
||||
var shadowRoot = $element[0].attachShadow({ mode: 'open' });
|
||||
shadowRoot.innerHTML = `
|
||||
<style>
|
||||
@import "${model.stylesheet}"
|
||||
</style>
|
||||
<div class="umb-block-list__block--view" ng-include="'${model.view}'"></div>
|
||||
`;
|
||||
$compile(shadowRoot)($scope);
|
||||
}
|
||||
else {
|
||||
$element.append($compile('<div class="umb-block-list__block--view" ng-include="model.view"></div>')($scope));
|
||||
}
|
||||
};
|
||||
$compile(shadowRoot)($scope);
|
||||
}
|
||||
else {
|
||||
$element.append($compile('<div class="umb-block-list__block--view" ng-include="model.view"></div>')($scope));
|
||||
}
|
||||
};
|
||||
|
||||
// We need to watch for changes on primitive types and upate the $scope values.
|
||||
model.$onChanges = function (changes) {
|
||||
if (changes.index) {
|
||||
var index = changes.index.currentValue;
|
||||
$scope.index = index;
|
||||
// We need to watch for changes on primitive types and update the $scope values.
|
||||
model.$onChanges = function (changes) {
|
||||
if (changes.index) {
|
||||
var index = changes.index.currentValue;
|
||||
$scope.index = index;
|
||||
|
||||
// let the Block know about the current index:
|
||||
model.block.index = index;
|
||||
model.block.updateLabel();
|
||||
}
|
||||
};
|
||||
}
|
||||
// let the Block know about the current index:
|
||||
if ($scope.block) {
|
||||
$scope.block.index = index;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user