views:

153

answers:

2

I have a GridPanel with just two columns: names and commission percentages. The sum of all of the percentages should never exceed a predetermined maximum (say that 25% of the sale is up for grabs).

Name          Commission
Bob           10%
Sally         15%

(Maximum is 25%)
Everything is fine.

I’ve attached a custom validator (see "validator") to the NumberField editor which works just great for complex logic on individual values, and I can sum up all of the values for the number column in the data store easily. But the problem is combining the two; the new value isn’t pushed to the store until after a successful validation, and the custom validator is only given the current value in question, with no context as to what row is involved (with which I could potentially subtract the old value, and use this new value in the total).

How can I get this validator to work in such a way that it makes sure that a newly entered value doesn’t push the sum over the maximum?

Name          Commission
Bob           10%
Sally         16% (Invalid!  Total commissions must not exceed 25%)

(Maximum is 25%)
A: 

You need to pull in the dirty value of the changed element before it is saved to the database. It does not make sense to validate the clean value after the fact.

See here for info on data storage in ExtJS:

http://www.fusioncube.net/index.php/managing-dirty-rows-in-a-sencha-extjs-editorgridpanel

You can use properties such as field.originalValue and field.getRawValue() to get at the data store and see the difference.

js1568
A: 

I didn’t quite use js1568’s answer, as I wanted to block bad values as they’re being entered; even before the AfterEdit event fires and the row gets marked dirty, and long before writing to the database. But that link did inspire me through its use of the grid’s selection model. So, my quick little solution:

Because the NumberField doesn’t pass any context to the custom validator (aside from the current value), using field.originalValue would have been awesome, but hey, life is hard.

But due to the fact that editing a row first requires selection of that row (and reinforced by the fact that this grid’s RowSelectionModel is set to SingleSelect), I know that the row being edited must be the only element in grid.selModel.selections.items[]. From there, it’s just a matter of

var newTotal = TotalCommissionPercentagesInGrid() – oldValue + newValue;

With oldValue being grid.selModel.selections.items[0].data.CommissionPercentage and newValue being the value passed to the validator function from the NumberField.

return ( newTotal <= percentageAvailable ) ? true : "No dice.";

Very nice.

Kevin L.
Glad I pointed you in the right direction. Good luck
js1568