I'm trying to build a custom component in Piranha called Table. It consists of a BlockGroup called TableBlock, which contains a BlockGroup called TableRowBlock, which itself contains a list of fields of type TableCellField.
I've never embedded a BlockGroup inside a BlockGroup before and not sure if it's possible, but I hope it is. A BlockGroup by default is rendered by the block-group (or block-group-horizontal?) Vue component in the admin, but I want to render it with my own custom Vue component.
It seems like even though I set the Component property on the BlockGroup, it ignores it and it still defaults to one of the default components for a BlockGroup, such as block-group or block-group-horizontal.
Is there any way to accomplish what I'm trying to do?
namespace Piranha.Extend.Blocks
{
[BlockGroupType(Name = "Table", Category = "Content", Icon = "fas fa-images", Component = "table-block")]
[BlockItemType(Type = typeof(TableRowBlock))]
public class TableBlock : BlockGroup
{
}
[BlockGroupType(Name = "Table Row", Category = "Content", Icon = "fas fa-images", Component = "table-row-block")]
[BlockItemType(Type = typeof(TableCellField))]
public class TableRowBlock : BlockGroup
{
public int RowNumber { get; set; }
public override string GetTitle()
{
return "Row";
}
}
}
namespace Piranha.Extend.Fields
{
[FieldType(Name = "TableCell", Shorthand = "Text", Component = "table-cell-field")]
public class TableCellField : IField
{
public string Value { get; set; }
public int ColumnNumber { get; set; }
public string GetTitle()
{
return !string.IsNullOrEmpty(ColumnNumber.ToString()) ? ColumnNumber.ToString() : "";
}
}
}
Here's the "table-block" Vue component:
<template>
<div :id="uid" class="block-group">
<table>
<template v-for="child in model.items">
<component v-bind:is="child.meta.component" v-bind:uid="child.meta.uid" v-bind:toolbar="toolbar" v-bind:model="child.model"></component>
</template>
</table>
</div>
</template>
<script>
export default {
props: ["uid", "toolbar", "model"],
methods: {
},
mounted: function () {
}
}
</script>
Here's the "table-row-block" Vue component:
<template>
<tr :id="uid" class="block-group">
<template v-for="child in model.items">
<component v-bind:is="child.meta.component" v-bind:uid="child.meta.uid" v-bind:toolbar="toolbar" v-bind:model="child.model" v-on:update-title="updateTitle($event)"></component>
</template>
</tr>
</template>
<script>
export default {
props: ["uid", "toolbar", "model"],
methods: {
},
mounted: function () {
var self = this;
}
}
</script>
Here's the "table-cell-field" Vue component:
<template>
<td :id="uid">
<input class="form-control" :placeholder="meta.placeholder" v-model="model.value" v-on:change="update()" type="text" />
<input class="form-control" v-model="model.columnNumber" type="hidden" />
</td>
</template>
<script>
export default {
props: ["uid", "model", "meta"],
methods: {
update: function () {
}
}
}
</script>
Unfortunately none of the things you’re trying to do is currently supported, that means:
The second one would be easy to support, and could be added in a service release. The first one however couldn’t be added without serious redesign of the editor UI/UX since the built in model doesn’t support collections on multiple levels.
The best solution with the current data model is to simply add a global field to the Table block that specifies the number of columns. This could then be used when rendering the custom block group component if support was added to this.