El valor del rasgo de casilla se muestra de forma diferente en vista (render()) frente al modelo (getHtml())
@mararn1618 ¿puedes crear una demo en directo reproducible de este número, por favor?
Lee la respuesta completa abajo ↓Pregunta
Tengo un componente personalizado con un rasgo de casilla de verificación 'mostrar-nombre'. Cuando el valor del rasgo es 'true', el componente se muestra en la vista al atributo showname="true", mientras que el modelo solo tiene "show-name" y se renderiza a "show-name" mediante getHtml().
¿Cómo puedo hacer que un rasgo de casilla de verificación se renderice en "showname=true" mediante getHtml()?
(Perdón por el código de referencia tan largo abajo ;-) )
Vista atribuida es show-name="true"
'<filter-wizard data-gjs-type="Feature (Enum)" filter-model="filterDAO.getFilterForPropertyProfileId(46)" pp-id="46" pp-type="4" show-name="true" data-highlightable="1" clase="gjs-comp-selected" style="width: 100%; display: block; addding: 16px; min-height: 160px; background-size: 60%; background-image: url("assets/feature_Enum_opa.png"); background-repeat: no-repeat; background-position: center center;"><center><label>Interfaces</label></center>'</filter-wizard>
El atributo modelo es solo el nombre de la mostra, pero no es "verdadero" (div es el mismo elemento que el asistente de filtro en la vista)
'<div class="row p-l-15 p-r-15 p-t-30 p-b-30 dpt-text-accent-dark ng-isolate-scope" filter-model="filterDAO.getFilterForPropertyProfileId(46)" pp-id="46" pp-type="4" nombre-de-mostrar></div>"
### El modelo JSON solo contiene el nombre del programa, pero no "verdadero"
'{"GJS-assets":"[]","GJS-CSS":"* { Tamaño-caja: Border-Box; } body {margin: 0;}","gjs-styles":"[]","gjs-html":"<filter-wizard filter-model="filterDAO.getFilterForPropertyProfileId(46)" pp-id="46" pp-type="4" show-name></filter-wizard>","gjs-components":":"{"tagName":"filter-wizard","type":"Feature (Enum),"name":"","removable":true,"arrastrable":true,"droppable":false,"badgable":true,"stylable":true,""unstylable":"resaltable":true,"copyable":true,"resizeable":false,"editable":false," layerable":true,"selectable":true,"hoverable":true,"void":false,"state":"","status":"content":"icon":"style":""styl","attributes":{"filter-model":"filterDAO.getFilterForPropertyProfileId(46)","pp-id":"46","pp-type":"4","show-name":true},"classes":[],"script":"traces":[{"type":"checkbox,"label":"mostrar nombre de la característica!","name":"show-name,"min":"maxim":"unit":"","step":1,"value":true,"default":"default":","placeholder":"","changeProp":0,"options:[]}, {"tipo":" select","label":"Alignment","name":"align","min":"","max":"","unit":","step":"value":""default":"default":"placeholder":"","changeProp":0,"options":[{{value":"left'","name":"Left"},{"value":"'center'","name":"Center"},{"value":"right'","name":"Right"}]},{"type":"string","label":"Reemplazar etiqueta cualquiera por ..","name":"label-any","min"","max":"unit":"","step":1,"value":"","default":"placeholder":"","changeProp":"options":[]},{"type":" número","etiqueta":"Forzar x columnas para la tabla de selección","nombre":"columnas-enum","min":""max":"","unidad":"","unidad":"paso":1,"valor":"","default":"","marcaposición":"""changeProp":0,"opciones":[]},{"tipo":"cadena","etiqueta":"Reemplazar etiqueta Irrelevante por ..","nombre":"etiqueta-irrelevante","min":"","max":","unidad":"","paso":1,"valor":"","default":""marcador":"""marcaposición":"cambioProp":0,"opciones":[]}],"propagar":"""mostrarNombre":true,"componentes":[],"open":false}]"}'
### Código de componentes (Typescript)
`
clase PPBlock {
id: cadena;
pp: propertyProfileModel;
etiqueta: cuerda;
Contenido: Cadena;
Categoría: Cuerda;
atributos: Objeto;
constructor(pp: propertyProfileModel) {
this.id = 'pp-filtro-' + pp.id;
this.pp = pp;
this.label = pp.name;
this.content = "";
this.category = "Características";
if(pp.type == ET.ET_PPType.Integer || pp.type == ET.ET_PPType.Float) {
this.label = svg_slider_two_handles + '<br/>' + this.label;
}
if(pp.type == ET.ET_PPType.Intervall) {
this.label = svg_slider + '<br/>' + this.label;
}
if(pp.type == ET.ET_PPType.String)
this.attributes = { clase: 'fa fa-i-cursor' };
if(pp.type == ET.ET_PPType.Enum || pp.type == ET.ET_PPType.Boolean)
this.attributes = { class: 'fa fa-th' };
this.buildContent();
}
buildContent(): void {
this.content = '<filter-wizard' +
'filter-model="filterDAO.getFilterForPropertyProfileId(' + this.pp.id + ')" ' +
'pp-id="' + this.pp.id + '"' +///usado en vista por componente para cargar más información sobre el propertyprofile
'pp-type="'+ this.pp.type +'"' + //usado para emparejar con el componente correcto
'pp-name="' + this.pp.name + //solo se usa para mostrar el nombre del componente
'>' +
'</filter-wizard>';
}
}
class PPComponent {
/* datos reales del componente */
etiquetaNombre: string = "asistente de filtro";
type: string;//se genera en un constructor a partir de ppType
modelo: cualquiera;
Visión: Cualquiera;
atributos: Objeto;
ppType: number;//ET.ET_PPType
ppTypePrinted: cadena;
propertyProfileModelService: propertyProfileModelService;
getView(): any { return this.view; }
getModel(): any { return this.model; }
constructor(editor: any, ppType: number, ppTypePrinted: string, propertyProfileModelService: propertyProfileModelService) {//ET.ET_PPType
sea defaultComponentType = editor. DomComponents.getType('default');
sea defaultModel = defaultComponentType.model;
sea defaultView = defaultComponentType.view;
Sea __this = esto;
this.propertyProfileModelService = propertyProfileModelService;
this.attributes = {};
this.ppType = ppType;
this.ppTypePrinted = ppTypePrinted;
this.type = "Feature (" + ppTypePrinted + ")";
/* modelo de construcción */
let modelDefaults: Object = this.helper_mergeobjects(defaultModel.prototype.defaults,
{
showName: cierto,
rasgos: this.buildTraits(),
Droppable: Falso
/*arrastrable: booleano = verdadero;
removible: booleano = verdadero;
droppable: booleano = falso;
estilizable: booleano = falso;
copiable: booleano = falso;
*/
}
);
this.model = defaultModel.extend(
{/* extiende el parámetro 1 */
valores predeterminados: modelValores predeterminados
},
/* extiende el parámetro 2, funciones estáticas */
{
isComponent(element: any): Object {
if(null == elemento || typeof element == 'indefinido')
regresar;
if(typeof element.tagName == 'indefinido')
regresar;
si(element.etiquetaNombre.toMajúscula() != __this.etiquetaNombre.toUpperCase())//elemento se inyecta en la versión mayúscula desde grapesjs por razones mágicas
regresar;
sea ppType_from_element: número = Número(elementoatributos['pp-type'].nodeValor);
if(ppType_from_element != __this.ppType)
regresar;
return {type: __this.type};
}
}
);
/* vista de construcción */
this.view = defaultView;
let defaultRender: Función = this.view.prototype.render;
this.view = defaultView.extend(
{
etiquetaNombre: 'div',
modelo: esto. modelo,
init: function() {
this.listenTo(this.model, 'change:attributes', this.render);
},
render: función () {
let view = this;//hack: this now NO se refiere a la instancia de class, sino a view
defaultView.prototype.render.apply(view);
ver.prototipo.render.apply(ver, nulo);
view.el.style.width = "100%";//¿necesitado?!
view.el.style.display = "block";//make full width
view.el.style.padding = "16px";//¿necesario?!
view.el.style.minHeight = "240px";
view.el.style.minHeight = "160px";
view.el.style.backgroundSize = "60%";
view.el.style.backgroundImage = "url('assets/feature_" + __this.ppTypePrinted + "_opa.png')";
view.el.style.backgroundRepeat = "no-repeat";
view.el.style.backgroundPosición = "centro";
build inner HTML
view.el.innerHTML = "";
sea ppid: number = Number(view.attr["pp-id"]);
if(null != ppid) {
sea pp: propertyProfileModel = __this.propertyProfileModelService.getPPById(ppid);
if(null != pp)
view.el.innerHTML += "<center><label>" + pp.name + "</label></center>";
}
/*no funciona
try {
sea ppTitle: string = view.el[0].attributes['pp-name'].nodeValue;
if(null != ppTitle)
view.el.innerHTML = "<center>" + ppTitle + "</center>";
} catch(e) {}
*/
Vista de retorno;
}
}
);
}
buildTraits(): Array<Object> {
Sea ret = [];
ret.push(
{
Tipo: 'Casilla de verificación',
etiqueta: '¡Nombre de la Función Mostra!',
Nombre: 'Nombre del Programa',
Valor: 'Verdadero',
cambioProp: 0
}
);
ret.push(
{
tipo: 'select',
etiqueta: 'Alineación',
Nombre: 'Align',
Opciones: [
{valor: '\'left'', nombre: 'Left'},
{valor: '\'Center'', nombre: 'Center'},
{valor: '\'right'', nombre: 'Right'}
],
cambioProp: 0
}
);
if(this.ppType == ET.ET_PPType.Enum) {
ret.push(
{//rasgo 3
Tipo: 'String',
etiqueta: 'Sustituye etiqueta cualquiera por ..',
Nombre: 'Label-Any',
cambioProp: 0
}
);
ret.push(
{//rasgo 3
Tipo: 'número',
etiqueta: 'Forzar x columnas para la tabla de selección',
Nombre: 'Columnas Enum',
cambioProp: 0
}
);
}
if(this.ppType == ET.ET_PPType.Boolean) {
ret.push(
{
Tipo: 'String',
etiqueta: 'Sustituye la etiqueta TRUE por ..',
Nombre: 'True-Label',
cambioProp: 0
}
);
ret.push(
{
Tipo: 'String',
etiqueta: 'Sustituye la etiqueta FALSE por ..',
Nombre: 'Etiqueta-falsa',
cambioProp: 0
}
);
}
if(this.ppType == ET.ET_PPType.Enum || this.ppType == ET.ET_PPType.Boolean) {
ret.push(
{//rasgo 3
Tipo: 'String',
etiqueta: 'Sustituir etiqueta Irrelevante por ..',
Nombre: 'Etiqueta-Irrelevante',
cambioProp: 0
}
);
}
return ret;
}
helper_mergeobjects(a: Objeto, b: Objeto): Objeto {
sea ret: Objeto = {};
para (clave var en la)
si (a.hasOwnProperty(key)) ret[key] = a[key];
para (clave var en b)
si (b.hasOwnProperty(key)) ret[key] = b[key];
return ret;
}
}
`Respuestas (3)
@mararn1618 ¿puedes crear una demo en directo reproducible de este número, por favor?
Hola @artf, por supuesto. He extraído las partes relevantes de mi proyecto y creado una demo junto con los pasos de reproducción:
- Demo: https://www.secretbakery.io/grapesjs/issue_1424.html
- Lista de archivos demo: https://www.secretbakery.io/grapesjs/
¡Gracias por cuidarte!
Edito: He añadido un archivo descargable de la demo a los archivos (grapesjs_1424.zip).
Ahora mismo estoy usando una solución alternativa para esto, de modo que mi directiva AngularJS —donde se debe usar este atributo— recalcule 'mostrar-nombre' como si tuviéramos 'mostrar-nombre="true"' en la etapa de enlace.
Solución alternativa a la Directiva AngularJS
Class filterWizardDirective implementa ng. IDirective {
/* .. código... */
link($scope: any, element: any, attrs: any) {
calcular explícitamente <nombre de mostrar el asistente de filtro>
if(null == $scope.showName || 'undefined' == tipo de $scope.showName || "" == $scope.showName) {
$scope.showName = 'showName' en attrs && "" == attrs.showName;
}
}
alcance: Objeto = {
Nombredel programa: "=?",
/* .. código... */
};
}
Preguntas y respuestas relacionadas
Continúa investigando con debates sobre temas similares.
Issue #1658
[BUG] El rasgo de casilla de verificación no carga como marcado incluso cuando el valor del rasgo es verdadero
Hola, Estoy usando la versión 0.14.33 de Grapesjs. Estoy cargando algunos componentes cuando carga el formulario y tengo un componente con...
Issue #1227
Volver a renderizar la vista en el lienzo del editor cada vez que cambie el valor del rasgo
¿Existe alguna forma posible en 'grapesjs' de que cada vez que un usuario cambia el valor de un 'Trait' de un 'componente' personalizado, l...
Issue #701
Modificar un componente en el editor elimina el contenido del modelo
Lo que intento conseguir: Tengo atributos especiales de "datos-" en algunos de los componentes que extrao al editor. Cuando uno de estos se...
Issue #1092
[BUG] rasgos y disparador de almacenamiento
Oye, quizá no sea un bicho, no estoy seguro. Tengo rasgos con changeProp: campo verdadero. Cuando cambio el valor del rasgo por interfaz, e...
Plugins de pago que cumplen con este problema
Seleccionado por temas clave y relevancia de etiquetas para ayudarte a enviar más rápido.
Cargando recomendaciones de plugins de pago...
Consulta los plugins de código abierto de GrapesJS en GitHub O haz una búsqueda rápida en nuestro catálogo gratuito.
Explora plugins gratuitos →Los plugins premium incluyen soporte, actualizaciones regulares y funciones listas para producción — ahorrando días de trabajo de integración.
Explora plugins premium →Tutoriales relacionados
Guías detalladas sobre el mismo tema.
Explorar categorías de plugins
Ve directamente a las páginas de categorías de plugins en el marketplace.