FieldContainer doesn't show correctly when you put labelAlign: 'top'.
Find my Fiddle : https://fiddle.sencha.com/#fiddle/1c2s
I create a custom field which is base on field container.
If you resize the window to a smaller size, you'll see that the textfield will go above the fieldContiner.
Any idea on how to fix this? Any workaround?
I've tried several stuff but I'm struggling... I don't now where I can act to change this...
And I definitly need to fix this.
Thanks in advance
(for reference: Open bug in Sencha forum: https://www.sencha.com/forum/showthread.php?311212-Fieldcontainer-incorrectly-displays-in-toolbar-with-label-aligned-top)
Looks like bug indeed, but there is pretty easy way to make that work - just set minHeight: 65 to your url field.
Fiddle: https://fiddle.sencha.com/#fiddle/1caa
I'm pretty sur I found the answer.
There is a mismatch between the build src and the doc!
If you check in your built source for file src/layout/component/field/FieldContainer.js you will notice that it doesn't correspond to the doc (and especially some method missing like calculateOwnerHeightFromContentHeight).
note: This has been fixed in ExtJs 6.2.0
Proposed override to fix this:
/**
* Override to fix componentLayout wrong calculation of height when labelAlign='top'
*
* See post forum:
* {#link https://www.sencha.com/forum/showthread.php?311212-Fieldcontainer-incorrectly-displays-in-toolbar-with-label-aligned-top}
*/
Ext.define('MyApp.overrides.layout.component.field.FieldContainer', {
override: 'Ext.layout.component.field.FieldContainer',
compatibility: [
'6.0.0',
'6.0.1',
'6.0.2'
],
/* Begin Definitions */
calculateOwnerHeightFromContentHeight: function(ownerContext, contentHeight) {
var h = this.callSuper([ownerContext, contentHeight]);
return h + this.getHeightAdjustment();
},
calculateOwnerWidthFromContentWidth: function(ownerContext, contentWidth) {
var w = this.callSuper([ownerContext, contentWidth]);
return w + this.getWidthAdjustment();
},
measureContentHeight: function(ownerContext) {
// since we are measuring the outer el, we have to wait for whatever is in our
// container to be flushed to the DOM... especially for things like box layouts
// that size the innerCt since that is all that will contribute to our size!
return ownerContext.hasDomProp('containerLayoutDone') ? this.callSuper([ownerContext]) : NaN;
},
measureContentWidth: function(ownerContext) {
// see measureContentHeight
return ownerContext.hasDomProp('containerLayoutDone') ? this.callSuper([ownerContext]) : NaN;
},
publishInnerHeight: function(ownerContext, height) {
height -= this.getHeightAdjustment();
ownerContext.containerElContext.setHeight(height);
},
publishInnerWidth: function(ownerContext, width) {
width -= this.getWidthAdjustment();
ownerContext.containerElContext.setWidth(width);
},
privates: {
getHeightAdjustment: function() {
var owner = this.owner,
h = 0;
if (owner.labelAlign === 'top' && owner.hasVisibleLabel()) {
h += owner.labelEl.getHeight();
}
if (owner.msgTarget === 'under' && owner.hasActiveError()) {
h += owner.errorWrapEl.getHeight();
}
return h + owner.bodyEl.getPadding('tb');
},
getWidthAdjustment: function() {
var owner = this.owner,
w = 0;
if (owner.labelAlign !== 'top' && owner.hasVisibleLabel()) {
w += (owner.labelWidth + (owner.labelPad || 0));
}
if (owner.msgTarget === 'side' && owner.hasActiveError()) {
w += owner.errorWrapEl.getWidth();
}
return w + owner.bodyEl.getPadding('lr');
}
}
});
Related
How do I restrict the drag operation not exceeding certain boundary. Is there any config in extjs (version 3), I saw that, Ext.dd.DragZone class is used. But Im not sure what is the usability. I saw a method dropNotAllowed. Is that the method, that has to be used? if so, how should I use that? Please provide some examples.
Im looking for something similar to (jquery UI's draggable containment property)
http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.dd.DragZone-cfg-dropNotAllowed
I tried using the set X and Y constraints, but it did not work-out:
abc.prototype.initDrag = function(v) {
v.dragZoneobj = new Ext.dd.DragZone(v.getEl(), {
getDragData : function(e) {
var sourceEl = e.getTarget(v.itemSelector, 10);
// sourceEl.setXConstraint( 0, 10 );
var t = e.getTarget();
var rowIndex = abc.grid.getView().findRowIndex(t);
var columnIndex = abc.grid.getView().findCellIndex(t);
if ((rowIndex !== false) && (columnIndex !== false)) {
if (sourceEl) {
abc.isDragged = true;
abc.scriptGrid.isDraggableForObject = false;
abc.scriptGrid.dragRowIndex = false;
d = sourceEl.cloneNode(true);
d.id = Ext.id();
d.textContent = sourceEl.innerHTML;
// d.setXConstraint( 0, 10 );
// d.setYConstraint( 0, 10 );
return {
ddel : d,
sourceEl : d,
sourceStore : v.store
}
}
}
},
getRepairXY : function() {
return this.dragData.repairXY;
},
});
}
Both are commented in the above code. The above code is initiated when the panel is rendered.
edit:
How these setX and setYcontraints have to be used?
By default, the element can be dragged any place on the screen. In the doc there are two methods setXConstraint( iLeft, iRight, iTickSize) and setYConstraint( iUp, iDown, iTickSize )
These two methods is used to set to limit the vertical travel and horizental travel of the element.
I'm trying to create a PercentField component that extends textfield for use on ExtJS forms. The behavior I'm looking for is for the field to display percent values, e.g. 25% or 400%, but have the underlying value when the user is editing the field or the form is being submitted be a decimal, e.g. .25 or 4.
I've succeeded in getting this working by using a renderer in a grid column, (Here's a fiddle) but it doesn't look like textfield has a renderer property for using the field in basic forms. I've looked at the rawToValue and valueToRaw methods, but they don't seem to be quite what I'm looking for. Any advice?
As far as I know, there's no possibility of template for form fields. That would require to flip the input element and display a div or something, on focus and blur. That would be doable, but that implies some fine tuned CSS.
A simpler option is to implement custom valueToRaw and rawToValue methods, and let Ext handles the value lifecycle (which is really the complicated part). You'll still have to change the raw value on focus and blur, but that remains pretty straightforward.
Here's an example you can build upon (see fiddle):
Ext.define('My.PercentTextField', {
extend: 'Ext.form.field.Text',
onFocus: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.rawToValue(v));
}
},
onBlur: function() {
this.callParent(arguments);
var v = this.getValue();
if (Ext.isNumeric(v)) {
this.setRawValue(this.valueToRaw(v));
}
},
valueToRaw: function(v) {
return Ext.isEmpty(v)
? ''
: v * 100 + ' %';
},
rawToValue: function(v) {
// cast to float
if (!Ext.isEmpty(v)) {
var pcRe = /^(\d*(?:\.\d*)?)\s*%$/,
dcRe = /^\d*(?:\.\d*)?$/,
precision = 2,
floatValue,
match;
if (match = dcRe.test(v)) { // decimal input, eg. .33
floatValue = v * 1;
} else if (match = pcRe.exec(v)) { // % input, eg. 33 %
floatValue = match[1] / 100;
} else {
// invalid input
return undefined;
}
floatValue = Number.parseFloat(floatValue);
if (isNaN(floatValue)) {
return undefined;
} else {
return floatValue.toFixed(precision);
}
} else {
return undefined;
}
}
});
Question Answer below
Hello I'm looking a simple way to change the colour of a progress bar, what I'm trying to do with it, would look like this:
function (progressBar, value) {
if (value < 40) {
progressBar.setColor('red');
} else if (value >= 40 && value <= 80) {
progressBar.setColor('yellow');
} else {
progressBar.setColor('green');
}
}
Then some kind of way to change the colour through the style with the method progressbar already have, setUI, or other kind of way that it could work would be great as well.
Thanks.
Solution
I found the way to do it, here it is, I create a custom progress bar, where I use the listener update, then this one is going to receive the actual value of the progress bar, and the bar itself, I take the obj and find the styles of the progress bar, where I modify backgroundColor and the borderRightColor with the hex color I want and set the backgroundImage to and empty URL then it will allow the backgroundcolor to show up.
Also I create the option to send a default color.
Here is the code:
Ext.define("progressBarCustom", {
extend: 'Ext.ProgressBar',
alias: 'widget.progressBarCustom',
max: null,
ave: null,
min: null,
color: null,
initComponent: function () {
var me = this;
me.width = 300;
me.margin = '5 5 0 5';
me.callParent(arguments);
},
listeners: {
update: function (obj, val) {
if (this.max != null && this.ave != null && this.min != null) {
if (val * 100 <= this.min) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#FF0000";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#FF0000";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
} else if (val * 100 <= this.ave) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#FFFF00";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#FFFF00";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
} else {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = "#009900";
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = "#009900";
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
}
} else if (this.color != null) {
obj.getEl().child(".x-progress-bar", true).style.backgroundColor = this.color;
obj.getEl().child(".x-progress-bar", true).style.borderRightColor = this.color;
obj.getEl().child(".x-progress-bar", true).style.backgroundImage = "url('')";
}
}
}
});
Then if you are going to create a new progressbar with the color changes here is the code:
Ext.create('progressBarCustom', {
min : 0.20,
ave : 0.60,
max : 0.80
});
or just with a default color:
Ext.create('progressBarCustom', {
color : "#4D0099"
});
Any suggestion would be received, thanks :).
I would suggest adding a listener that calls your function on the move event as this appears to contain the positions you need. Documentation link.
For the setColor aspect I believe you want to set the components style elements. Documentation link. Hope that helps.
does any body know how to show the horizontal scroller on tree panel...
since it describe here, the bugs will be fix in 4.1.x version,...
cause i'm not satisfied, i try to googling to find the hot fix,.
and i got this, Mr. Edspencer suggest to using ext 4.0.6....
but, it still not working,. (tested version 4.0.7)
anybody know how to fix this???
I have some workaround. See code below.
afterrender: function() {
var view = this.getView();
var c = view.container;
var e = view.el;
var max = 0;
Ext.each(e.query('.x-grid-cell-inner'), function(el) {
el = Ext.get(el);
var size = el.getPadding('lr');
Ext.each(el.dom.childNodes, function(el2){
if (el2.nodeType == 3) {
size += 6 + el.getTextWidth(el2.nodeValue);
} else {
size += Ext.get(el2).getWidth();
}
});
max = Math.max(max, size);
});
max += c.getPadding('lr');
if (c.getWidth() < max) {
c.dom.style.overflowX = 'scroll';
e.setWidth(max);
e.down('table').setWidth(max);
}
}
You only need to add this listener to your TreePanel. Basically it finds width of wider element and extend width of table, switch overflow on container.
Working sample: http://jsfiddle.net/Uf7yy/2/
EXT version 3.3.0
I have a grid panel with sortable columns. It works with 90% of the users. But with some users, the first column (which is an integer) renders as not sortable. Even when you click on the pop up menu above the column, the "Sort Ascending" and "Sort Descending" are greyed out. I cannot replicate this error, but I have seen it on other user workstations. Here are more details:
The ColoumnModel uses a RowNumberer
All columns are sortable.
The grid panel uses a viewConfig w/ "forceFit" set to false, and "autoFill" set to true.
I don't have the source code on this network, o/w I would just paste it in.
Thanks!
I remember I had similar issue some time ago, and the deal was that ExtJs grid restores it's state from cookies incorrectly. After some debugging I added the following patch:
Ext.override(Ext.grid.GridPanel, {
applyState: function (state) {
var cm = this.colModel,
cs = state.columns,
store = this.store,
s,
c,
colIndex;
if (cs) {
for (var i = 0, len = cs.length; i < len; i++) {
s = cs[i];
c = cm.getColumnById(s.id);
if (c) {
colIndex = cm.getIndexById(s.id);
cm.setState(colIndex, {
hidden: s.hidden,
width: s.width,
sortable: s.sortable,
fixed: cm.columns[colIndex].fixed
});
if (colIndex != i) {
cm.moveColumn(colIndex, i);
}
}
}
}
if (store) {
s = (state.sort instanceof Array) ? state.sort[0] : state.sort;
if (s) {
store[store.remoteSort && store.groupBy ? 'setDefaultSort' : 'sort'](s.field, s.direction);
}
s = state.group;
if (store.groupBy) {
if (s) {
store.groupBy(s);
}
else {
store.clearGrouping();
}
}
}
var o = Ext.apply({}, state);
delete o.columns;
delete o.sort;
Ext.grid.GridPanel.superclass.applyState.call(this, o);
}
});
The only extra thing it does it restore fixed property from the cookies as well.