É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.
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.
});
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
Vous devez vous connecter pour publier un commentaire.
Avez-vous essayé de mettre
autoRender: true
dans votre composants optionnels? Voici la doc: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.AbstractComponent-cfg-autoRenderPas sûr que je peux recommander quoi que ce soit, sans voir le code.
autoRender
n'travail en général, mais il y a peut être quelque chose dans votre code qui casse la logique et les forces de l'composants à rendre.OK, j'ai ajouté quelques extraits de notre code.
Votre réponse ne résout pas le problème, mais c'était de loin le meilleur, donc j'ai décidé de l'attribution de la prime à vous. Nous sommes encore sur cette question et de la pensée, nous pouvons rouvrir ce avec des informations plus détaillées (et une plus grande générosité 😉 )
OriginalL'auteur Alex Tokarev
Vous pouvez essayer de masquer et d'afficher les fonctions et aussi essayer avec ", a ajouté l'écouteur d'événement, qui sera appelé après l'ajout du composant dans le récipient.
Et par la façon dont
setVisible
appels masquer/afficherOriginalL'auteur Chandra
Essayer quelque chose comme cela pour votre plugin:
Hmm, eh bien, alors vous avez besoin de regarder
Ext.app.portal.PortalColumn
composant et de voir ce qui doit être fait-il tant de mise en page ne se cassent pas quand l'un de ses éléments n'est pas rendu. Je n'ai pas tout à fait ce que tu veux dire par "à Côté, c'est que les observables de l'instance n'est pas prêt de l'hôte. Si vous ne voulez pas avoir à rendre de composants, alors vous devriez utiliserinit
méthode et des événements (à mon avis), ou ne pas ajouter des composants comme des éléments qui, si elles ne doivent pas être visibles. Est-ce possible de la solution dans votre cas? peut-être que vous pouvez aussi appeler "supprimer" sur le composant parent à l'intérieur de plugin en quelque sorte... JSFiddle aiderait vraiment.Je l'ai ajouté à la question. Notez que le portail est fondamentalement la même (addPortlet!) livré par sencha. Ce que je voulais dire avec " ... " c'est que je ne peux pas faire ça dans le plugin constructeur parce que l'hôte n'est pas prête à ce moment. Fondamentalement, nous sommes à la recherche d'une solution légère. Fait est que nous ne pouvons pas arrêter le processus de création du composant donc, à moins que l'on puisse l'empêcher d'être rendu (à moins qu'on le pensait). Maintenant il semble qu'il n'est pas possible de prévenir le rendu d'un composant de façon propre. Rappelez-vous que le portail est livré par sencha avec tous les ExtJS version.
OriginalL'auteur sbgoran