Éviter de Rendu (masquer et/ou de désactiver) d'un Composant au moment de la construction

Contexte: Notre application est toujours emballé dans son ensemble, mais par les utilisateurs d'accéder à certains serverside actions peut être restreinte. Nous savons quelles sont les actions a permis à la fois l'application démarre. Maintenant, nous voulons cacher tous les points de vue (panneaux, boutons, etc) de l'utilisateur à qui il manque de l'accès à l'.

Pour cela, nous avons écrit un plugin qui peut être appliquée à n'importe quel Composant. Mais voici le problème:

Ici est ce que nous essayons de courir contre le plugin de l'hôte:

if (cmp['setVisible']) cmp.setVisible(false); else cmp.hidden = true;
if (cmp['disable']) cmp.disable(); else cmp.disabled = true;
cmp.on('beforerender', function() { return false; })

Nous avons d'abord pensé que le plus tôt nous le faisons, mieux. Nous avons donc essayé de l'exécuter au moment de la construction du plugin. Mais ce n'était pas possible parce que les auditeurs (de l'hôte) ne semble pas être encore prête (le composant essaie de feu l'événement masquer). Donc, nous avons déménagé dans le init méthode du plugin qui ne jette pas une erreur, mais juste a travaillé en partie. Seul le beforerender événement s'est vraiment appliqué, mais il ne interrompu le rendu de l'enfant. nous avons donc fini avec une fracture à la recherche de composants (les frontières sont là et que le contenu n'est pas). Si l'on a commenté l'événement d'enregistrement de l'hôte est resté intact. Nous avons également testé l'utilisation de seulement les hidden:true et disabled:true avec pas de chance.

Alors, comment pouvons-nous empêcher de rendu de la composante dans le bon chemin?

Edit:

Le composant en question doit être marqué comme désactivé et cachés parce que nous ne pouvons pas empêcher la création du composant. L'aide de l'extrait que j'ai de mon collègue était mauvais donc, l'appel de setVisible(false) travaillé, on devine disable() aussi. Mais les composants, apaisé rendu et nous ne semblent pas vraiment en mesure d'opposer un veto sans se retrouver avec un demi-rendu de la composante.

Réponse par @AlexTokarev

J'ai essayé ce que @AlexTokarev suggéré. Pour cela, j'ai ajouté les lignes suivantes dans le Plugin-Constructeur

cmp.hidden = true;
cmp.autoShow = false; //I know this may do nothing for non floating but I added it anyway
cmp.autoRender = true;

Basé sur le débogage je sais que les paramètres appliquée très tôt (à l' Ext.AbstractComponent.constructeur), mais j'ai encore de se retrouver avec un caché et le rendu d'un composant.

Éviter de Rendu (masquer et/ou de désactiver) d'un Composant au moment de la construction

Commentaire par @sbgoran

Dans un cas de test, nous utilisons une colonne-modèle dans lequel tous les conteneurs étendre à partir de la même classe. Dès que j'ai ajouter notre plugin (avec l'événement beforerender retourner false configuration) à la une de cette l'extension de conteneurs (le plugin est directement ajouté à la définition de la classe (comme ptype)) tous les conteneurs à l'intérieur de cette colonne look cassé (seulement les frontières sont rendus et dans le contenu d'une petite boîte grise dans le coin supérieur gauche.). Donc avorté rendu affecter tous les éléments enfants de la colonne lorsqu'un seul élément enfant d'obtenir le rendu annulée.

**Exemple De Code **

D'abord je tiens à noter que nous sommes à la recherche d'un moyen de le faire dans les causes que l'on sache, le rendu dans ExtJS est une chose. Je peux demander à l'installation d'une démo, mais je pense que ce ne sera pas facile parce que nous sommes à l'aide de la Ext.app.portal.Panel pour l'exemple d'échec. mais le plugin devrait fonctionner pour n'importe quel genre de Composant. D'abord, je vais ajouter un peu de code de démonstration:

Nous avons un point de vue qui est placé dans un Viwport à la frontière de disposition

Ext.define('MVC.view.Application',{
    extend:'Ext.tab.Panel',
    alias:'widget.appview',
    region: 'center',
    activeTab: 1
});

Dans le Contrôleur de nous remplir ce

var portal = this.portalRef = Ext.widget('portalpanel', {
    title: 'Employee',
    portalCols: 2
});
portal.addPortlet(0,['employee','employee2','employee3']);
portal.addPortlet(1,['employee4','employee5']);
app.appviewmain.add(portal);

Ici est le portail panneau

Ext.define('MVC.app.portal.PortalPanel', {
extend: 'Ext.panel.Panel',
alias: 'widget.portalpanel',
requires: [
'Ext.layout.container.Column',
'Ext.app.portal.PortalDropZone',
'Ext.app.portal.PortalColumn'
],
portalCols: 2,
portalColCfg: {
defaults: {
closable: false,
draggable: false,
collapsible: false,
header: false,
bodyStyle: {
background: '#fff',
padding: '10px'
}
},
items: []
},
addPortlet: function(idx, portlets) {
if (idx > this.portalCols || idx < 0)
return;
var portalCol = this.items.getAt(idx);
function insertPortlet(portlet) {
if (Ext.isString(portlet)) {
portlet = { xtype: portlet };
}
portalCol.add(portlet);
};
if (Ext.isArray(portlets)) {
var len = portlets.length,
i = 0;
for(;i<len;i++) {
insertPortlet(portlets[i]);
}
}  else  {
insertPortlet(portlets);
}
},
initPortal: function() {
var cfg = this.portalColCfg,
i = 0,
cols = [];
for (;i<this.portalCols;i++) {
cols.push(Ext.clone(cfg));
}
this.items = cols;
},
cls: 'x-portal',
bodyCls: 'x-portal-body',
defaultType: 'portalcolumn',
autoScroll: true,
manageHeight: false,
initComponent : function() {
var me = this;
//init only if nothing is defined
if (!me.items)
me.initPortal();
//Implement a Container beforeLayout call from the layout to this Container
me.layout = {
type : 'column'
};
me.callParent();
me.addEvents({
validatedrop: true,
beforedragover: true,
dragover: true,
beforedrop: true,
drop: true
});
},
//Set columnWidth, and set first and last column classes to allow exact CSS targeting.
beforeLayout: function() {
var items = this.layout.getLayoutItems(),
len = items.length,
firstAndLast = ['x-portal-column-first', 'x-portal-column-last'],
i, item, last;
for (i = 0; i < len; i++) {
item = items[i];
item.columnWidth = 1 / len;
last = (i == len-1);
if (!i) { //if (first)
if (last) {
item.addCls(firstAndLast);
} else {
item.addCls('x-portal-column-first');
item.removeCls('x-portal-column-last');
}
} else if (last) {
item.addCls('x-portal-column-last');
item.removeCls('x-portal-column-first');
} else {
item.removeCls(firstAndLast);
}
}
return this.callParent(arguments);
},
//private
initEvents : function(){
this.callParent();
this.dd = Ext.create('Ext.app.portal.PortalDropZone', this, this.dropConfig);
},
//private
beforeDestroy : function() {
if (this.dd) {
this.dd.unreg();
}
this.callParent();
}
});

Et voici le Portlet

Ext.define('Ext.app.portal.Portlet', {
extend: 'Ext.panel.Panel',
alias: 'widget.portlet',
layout: 'fit',
anchor: '100%',
frame: true,
closable: true,
collapsible: true,
animCollapse: true,
draggable: {
moveOnDrag: false    
},
cls: 'x-portlet',
initComponent : function() {
this.callParent();
},
//Override Panel's default doClose to provide a custom fade out effect
//when a portlet is removed from the portal
doClose: function() {
if (!this.closing) {
this.closing = true;
this.el.animate({
opacity: 0,
callback: function(){
var closeAction = this.closeAction;
this.closing = false;
this.fireEvent('close', this);
this[closeAction]();
if (closeAction == 'hide') {
this.el.setOpacity(1);
}
},
scope: this
});
}
}
});

Voici un exemple de vue

Ext.define('MVC.view.employee.Employee',{
extend:'Ext.app.portal.Portlet',
alias:'widget.employee',
plugins: [{ptype: 'directbound', accessRoute: 'Employee.Read'}],
items: [
/*A form with some fields*/
]
});

Voici le plugin

Ext.define('MVC.direct.plugins.DirectBound',{
extend: 'Ext.AbstractPlugin',
alternateClassName: ['MVC.direct.DirectBound'],
alias: 'plugin.directbound',
/**
* @cfg {int} blockMode Indicates the way in which the Component gets blocked
* options
* 0 hide and disable
* 1 disable
*/
blockMode: 1,
constructor: function(config) {
var me = this,
cmp = config['cmp'], 
route;
me.parseRoute(route);
//check for access
if (!me.checkAccess()) {
if (me.blockMode === 0) {
cmp.hidden = true;
cmp.autoShow = false;
cmp.autoRender = true;
}
me.diabled = true;
}
me.callParent(arguments);
}
/* some more methods */
});

Voici la Présentation en colonne

Ext.define('MVC.app.le portail.PortalColumn', {
étendre: 'Ext.le conteneur.Conteneur',
alias: 'widget.portalcolumn',

requires: [
'Ext.layout.container.Anchor',
'MVC.app.portal.Portlet'
],
layout: 'anchor',
defaultType: 'portlet',
cls: 'x-portal-column'
//This is a class so that it could be easily extended
//if necessary to provide additional behavior.

});

Qu'entendez-vous par the listeners seems to be not ready yet ? Si vous voulez déclencher des événements à partir de votre plugin, vous devrez étendre à partir d'observables. Peut-être que c'est votre erreur?
Je voulais dire que les auditeurs de l'hôte.
Je pense que le retour de faux à l'intérieur de beforerender de rappel devrait fonctionner. Peut-être que vous avez un problème avec un composant conteneur qui se termine sans enfant, mais lui-même est visible (pris cette forme votre "les frontières sont là et que le contenu n'est pas"). Donc, vous pourriez avoir besoin de tester si items propriété pour containable composants sont vides et l'ensemble des éléments vides composants de ne pas trop visible.
Eh bien, je doute que. Parce que tous les conteneurs à l'intérieur de la colonne (dans un cas de test, nous utilisons une mise en page en colonnes) sont vides lors de l'utilisation de l'événement tout en un seul conteneur abandonné la mise en page (tous les autres ont même pas le plugin et oui, le plugin est directement attribué à le conteneur dans lequel tous les conteneurs s'étendent à partir de la même classe).
Pourriez-vous nous fournir un exemple de code qui ne fonctionne pas, il serait encore mieux de mettre en place un test de cas dans JSFiddle ou similaires et de nous montrer exactement ce problème que vous avez, je pense, qui permettrait d'accélérer les choses et de les limiter à des questions supplémentaires 😉

OriginalL'auteur JJR | 2013-10-06