Extjs Set fieldLabel dynamically fires only once - extjs

I've tried this:
Ext.override(Ext.form.Field, {
setFieldLabel: function(text) {
if (this.rendered) {
var labelSeparator = this.labelSeparator;
if (typeof labelSeparator == 'undefined') {
if (this.ownerCt && this.ownerCt.layout && typeof
this.ownerCt.layout.labelSeparator != 'undefined')
labelSeparator = this.ownerCt.layout.labelSeparator;
else
labelSeparator = '';
}
var formItem = this.el.up('.x-form-item', 10);
if (formItem) {
var label = formItem.child('.x-form-item-label');
if (label)
label.update(text + labelSeparator);
}
} else
this.fieldLabel = text;
}
})
but it only fires once.
I have a formpanel (form a) that lets you edit a set of data, and that set of data will be the fieldLabel of another form (form b). At start, when I "edit" the fieldLabel from form a, it works, (form b's fieldLabel is changed), but after opening form b from a button (e.i. Create button), and editting the fieldLabel (inputtin in a textfield) from form a again, the fieldLabel in form b is not changed.
formItem = this.el.up('.x-form-item', 10); becomes null.
how to resolve this?
Thanks.

Solve:
Ext.override(Ext.form.Field, {
setFieldLabel: function(text) {
if (this.rendered) {
var labelSeparator = this.labelSeparator;
if (typeof labelSeparator == 'undefined') {
if (this.ownerCt && this.ownerCt.layout && typeof this.ownerCt.layout.labelSeparator != 'undefined')
labelSeparator = this.ownerCt.layout.labelSeparator;
else
labelSeparator = '';
}
var formItem = this.el.up('.x-form-item', 10);
if (formItem) {
var label = formItem.child('.x-form-item-label');
if (label)
label.update(text + labelSeparator);
} else {
this.labelEl.update(text);
}
} else {
this.fieldLabel = text;
}
}
});

Just call setText() method. More simple.

Related

Isotope: Combined multiple checkbox and searchbox filtering

I'm trying to combine the Isotope multiple checkbox filtering with a searchbox.
I used the example with the checkbox filters from here and tried to implement the searchbox but with no luck.
Just the checkbox filtering works well. I think i'm close to the solution but my javascript skills are at a very beginner level.
I commented out the section of what i've tried to implement.
Thank you for some hints
// quick search regex
var qsRegex;
var $grid;
var filters = {};
var $grid = $('.grid');
//set initial options
$grid.isotope({
layoutMode: 'fitRows'
});
$(function() {
$grid = $('#grid');
$grid.isotope();
// do stuff when checkbox change
$('#options').on('change', function(jQEvent) {
var $checkbox = $(jQEvent.target);
manageCheckbox($checkbox);
var comboFilter = getComboFilter(filters);
/*var searchResult = qsRegex ? $(this).text().match(qsRegex) : true;
var filterResult = function() {
return comboFilter && searchResult;
}*/
$grid.isotope({
filter: comboFilter //or filterResult
});
});
});
function getComboFilter(filters) {
var i = 0;
var comboFilters = [];
var message = [];
for (var prop in filters) {
message.push(filters[prop].join(' '));
var filterGroup = filters[prop];
// skip to next filter group if it doesn't have any values
if (!filterGroup.length) {
continue;
}
if (i === 0) {
// copy to new array
comboFilters = filterGroup.slice(0);
} else {
var filterSelectors = [];
// copy to fresh array
var groupCombo = comboFilters.slice(0); // [ A, B ]
// merge filter Groups
for (var k = 0, len3 = filterGroup.length; k < len3; k++) {
for (var j = 0, len2 = groupCombo.length; j < len2; j++) {
filterSelectors.push(groupCombo[j] + filterGroup[k]); // [ 1, 2 ]
}
}
// apply filter selectors to combo filters for next group
comboFilters = filterSelectors;
}
i++;
}
var comboFilter = comboFilters.join(', ');
return comboFilter;
}
// use value of search field to filter
var $quicksearch = $('.quicksearch').keyup(debounce(function() {
qsRegex = new RegExp($quicksearch.val(), 'gi');
$grid.isotope();
}, ));
// debounce so filtering doesn't happen every millisecond
function debounce(fn, threshold) {
var timeout;
threshold = threshold || 100;
return function debounced() {
clearTimeout(timeout);
var args = arguments;
var _this = this;
function delayed() {
fn.apply(_this, args);
}
timeout = setTimeout(delayed, threshold);
}
}
function manageCheckbox($checkbox) {
var checkbox = $checkbox[0];
var group = $checkbox.parents('.option-set').attr('data-group');
// create array for filter group, if not there yet
var filterGroup = filters[group];
if (!filterGroup) {
filterGroup = filters[group] = [];
}
var isAll = $checkbox.hasClass('all');
// reset filter group if the all box was checked
if (isAll) {
delete filters[group];
if (!checkbox.checked) {
checkbox.checked = 'checked';
}
}
// index of
var index = $.inArray(checkbox.value, filterGroup);
if (checkbox.checked) {
var selector = isAll ? 'input' : 'input.all';
$checkbox.siblings(selector).prop('checked', false);
if (!isAll && index === -1) {
// add filter to group
filters[group].push(checkbox.value);
}
} else if (!isAll) {
// remove filter from group
filters[group].splice(index, 1);
// if unchecked the last box, check the all
if (!$checkbox.siblings('[checked]').length) {
$checkbox.parents('.option-set').find(selector).prop('checked', false);
}
}
I found the solution by myself, but i had to add a second function for returning the searchresult. Otherwise the search function is triggered only after using a checkbox or leaving the search box input field.
How could i avoid this redundand code?
JS:
// use value of search field to filter
var $quicksearch = $('.quicksearch').keyup(debounce(function() {
qsRegex = new RegExp($quicksearch.val(), 'gi');
$grid.isotope();
}, 200));
$(function() {
$grid = $('#grid');
$grid.isotope({
filter: function() {
var searchResult = qsRegex ? $(this).text().match(qsRegex) : true;
return searchResult;
}
});
// do stuff when checkbox change
$('#options').on('change', function(jQEvent) {
var $checkbox = $(jQEvent.target);
manageCheckbox($checkbox);
var comboFilter = getComboFilter(filters);
$grid.isotope({
filter: function() {
var buttonResult = comboFilter ? $(this).is(comboFilter) : true;
var searchResult = qsRegex ? $(this).text().match(qsRegex) : true;
return buttonResult && searchResult;
}
});
});
});

How to add thousand separating commas for numbers in angularJS?

I simply want to convert a string of numbers to a number which will be displayed using thousand separated commas.
var value = "123456";
I want to display "123,465" in a grid.
I have looked some documentation on this but everything is about displaying it in HTML.
I want to display this in a dynamic grid.
function numberRenderer (params) {
return new Number (params.value);
}
I want to format the number so that I can convert that into a string for display.
Use a filter ...
HTML usage
{{ number_expression | number : fractionSize}}
Js usage
$filter('number')(number, fractionSize)
I appreciated the answer from #jbrown, but I was also hoping to find some type of solution to add commas to an input field as the user enters numbers. I ended up finding this directive which proved to be exactly what I needed.
HTML
<input type="text" ng-model="someNumber" number-input />
JAVASCRIPT
myApp.directive('numberInput', function($filter) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.push(function(modelValue) {
return setDisplayNumber(modelValue, true);
});
// it's best to change the displayed text using elem.val() rather than
// ngModelCtrl.$setViewValue because the latter will re-trigger the parser
// and not necessarily in the correct order with the changed value last.
// see http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/
// for an explanation of how ngModelCtrl works.
ngModelCtrl.$parsers.push(function(viewValue) {
setDisplayNumber(viewValue);
return setModelNumber(viewValue);
});
// occasionally the parser chain doesn't run (when the user repeatedly
// types the same non-numeric character)
// for these cases, clean up again half a second later using "keyup"
// (the parser runs much sooner than keyup, so it's better UX to also do it within parser
// to give the feeling that the comma is added as they type)
elem.bind('keyup focus', function() {
setDisplayNumber(elem.val());
});
function setDisplayNumber(val, formatter) {
var valStr, displayValue;
if (typeof val === 'undefined') {
return 0;
}
valStr = val.toString();
displayValue = valStr.replace(/,/g, '').replace(/[A-Za-z]/g, '');
displayValue = parseFloat(displayValue);
displayValue = (!isNaN(displayValue)) ? displayValue.toString() : '';
// handle leading character -/0
if (valStr.length === 1 && valStr[0] === '-') {
displayValue = valStr[0];
} else if (valStr.length === 1 && valStr[0] === '0') {
displayValue = '';
} else {
displayValue = $filter('number')(displayValue);
}
// handle decimal
if (!attrs.integer) {
if (displayValue.indexOf('.') === -1) {
if (valStr.slice(-1) === '.') {
displayValue += '.';
} else if (valStr.slice(-2) === '.0') {
displayValue += '.0';
} else if (valStr.slice(-3) === '.00') {
displayValue += '.00';
}
} // handle last character 0 after decimal and another number
else {
if (valStr.slice(-1) === '0') {
displayValue += '0';
}
}
}
if (attrs.positive && displayValue[0] === '-') {
displayValue = displayValue.substring(1);
}
if (typeof formatter !== 'undefined') {
return (displayValue === '') ? 0 : displayValue;
} else {
elem.val((displayValue === '0') ? '' : displayValue);
}
}
function setModelNumber(val) {
var modelNum = val.toString().replace(/,/g, '').replace(/[A-Za-z]/g, '');
modelNum = parseFloat(modelNum);
modelNum = (!isNaN(modelNum)) ? modelNum : 0;
if (modelNum.toString().indexOf('.') !== -1) {
modelNum = Math.round((modelNum + 0.00001) * 100) / 100;
}
if (attrs.positive) {
modelNum = Math.abs(modelNum);
}
return modelNum;
}
}
};
});
AngularJS Directive was found from: AngularJS number input formatted view
https://jsfiddle.net/benlk/4dto9738/
Very appreciative of what Anguna posted. The only thing it was missing for me was handling the decimal places like currency. I wanted it to automatically add 2 decimal places to the displayed value. However, this should only occur on initial display and then again when leaving a field. I updated the code to handle that scenario.
var app = angular.module("myApp", []);
app.directive('currencyInput', function ($filter) {
return {
require: 'ngModel',
link: function (scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.push(function (modelValue) {
var displayValue = setDisplayNumber(modelValue, true);
displayValue = setDecimal(displayValue);
return displayValue;
});
// it's best to change the displayed text using elem.val() rather than
// ngModelCtrl.$setViewValue because the latter will re-trigger the parser
// and not necessarily in the correct order with the changed value last.
// see http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/
// for an explanation of how ngModelCtrl works.
ngModelCtrl.$parsers.push(function (viewValue) {
setDisplayNumber(viewValue);
return setModelNumber(viewValue);
});
// occasionally the parser chain doesn't run (when the user repeatedly
// types the same non-numeric character)
// for these cases, clean up again half a second later using "keyup"
// (the parser runs much sooner than keyup, so it's better UX to also do it within parser
// to give the feeling that the comma is added as they type)
elem.bind('keyup focus', function () {
setDisplayNumber(elem.val());
});
elem.bind('blur', function () {
// Add Decimal places if they do not exist
var valStr = elem.val().toString();
valStr = setDecimal(valStr);
elem.val(valStr);
});
function setDisplayNumber(val, formatter) {
var valStr, displayValue;
if (typeof val === 'undefined') {
return 0;
}
valStr = val.toString();
displayValue = valStr.replace(/,/g, '').replace(/[A-Za-z]/g, '');
displayValue = parseFloat(displayValue);
displayValue = (!isNaN(displayValue)) ? displayValue.toString() : '';
// handle leading character -/0
if (valStr.length === 1 && valStr[0] === '-') {
displayValue = valStr[0];
} else if (valStr.length === 1 && valStr[0] === '0') {
displayValue = '';
} else {
displayValue = $filter('number')(displayValue);
}
// handle decimal
if (!attrs.integer) {
if (displayValue.indexOf('.') === -1) {
if (valStr.slice(-1) === '.') {
displayValue += '.';
} else if (valStr.slice(-2) === '.0') {
displayValue += '.0';
} else if (valStr.slice(-3) === '.00') {
displayValue += '.00';
}
} // handle last character 0 after decimal and another number
else {
if (valStr.slice(-1) === '0') {
displayValue += '0';
}
}
}
if (attrs.positive && displayValue[0] === '-') {
displayValue = displayValue.substring(1);
}
if (typeof formatter !== 'undefined') {
return (displayValue === '') ? 0 : displayValue;
} else {
elem.val((displayValue === '0') ? '' : displayValue);
}
}
function setModelNumber(val) {
var modelNum = val.toString().replace(/,/g, '').replace(/[A-Za-z]/g, '');
modelNum = parseFloat(modelNum);
modelNum = (!isNaN(modelNum)) ? modelNum : 0;
if (modelNum.toString().indexOf('.') !== -1) {
modelNum = Math.round((modelNum + 0.00001) * 100) / 100;
}
if (attrs.positive) {
modelNum = Math.abs(modelNum);
}
return modelNum;
}
function setDecimal(val) {
// Add Decimal places if they do not exist
var valStr = val.toString();
// If no decimal then add it
if (valStr.indexOf('.') === -1) {
valStr += '.00';
}
else {
var decimalDigits = valStr.length - (valStr.indexOf('.') + 1);
var missingZeros = 2 - decimalDigits;
for (var i = 1; i <= missingZeros; i++) {
valStr += '0';
}
}
return valStr;
}
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script>
<div ng-app="myApp">
<input type="text" ng-model="myModelValue" currency-input />
</div>

angular - factory error 'service not defined'

Getting into Angular. I'm trying to set up a factory to store animation functions. Only thing I get is 'service is not defined' in the console. Here's a codepen link: http://codepen.io/tplummerptc/pen/dGbKOp
var app = angular.module('App', []);
app.factory('soarimation', function(){
service.soarFlash = function(target, color) {
target = (target == undefined) ? false : target;
color = (color != 'default') ? 'defualt' : color;
// Set animation color
if(color != 'default') {
var aniClass = 'flash-'+color;
} else {
var aniClass = 'flash';
}
if(!target) {
$(this)
.closest(target)
.addClass(aniClass)
.delay(1000)
.queue(function(next){
$(this).removeClass(aniClass);
next();
});
} else {
$(this)
.addClass(aniClass)
.delay(1000)
.queue(function(next){
$(this).removeClass(aniClass);
next();
});
}
}
});
app.controller('addRow',function($scope, soarimation){
$scope.submitRow = function(event){
angular.element(event.currentTarget).soarFlash('li');
}
});
Factories in angularjs always return a object. You have to declare the service object inside app.factory method and then add the desired functions and variables to it. Finally return that object. You can use this object in your controller by using the factory name.
app.factory('soarimation', function(){
var service = {}; //Declaring the object
service.soarFlash = function(target, color) {
target = (target == undefined) ? false : target;
color = (color != 'default') ? 'defualt' : color;
// Set animation color
if(color != 'default') {
var aniClass = 'flash-'+color;
} else {
var aniClass = 'flash';
}
if(!target) {
$(this)
.closest(target)
.addClass(aniClass)
.delay(1000)
.queue(function(next){
$(this).removeClass(aniClass);
next();
});
} else {
$(this)
.addClass(aniClass)
.delay(1000)
.queue(function(next){
$(this).removeClass(aniClass);
next();
});
}
}
return service; // Return the object
});
app.controller('addRow',function($scope, soarimation){
$scope.submitRow = function(event){
var elem = angular.element(event.currentTarget);
soarimation.soarFlash(elem);
}
});

Access to scope variable in custom directive dynamically

I try to write a dynamic field validation. if a check box is checked a new section is shown in my page. As a result, in the new section some new inputs should be filled.
I write a custom directive like this
<input .... multiValidation="Street,City,PostalCode" />
my directive code is
app.directive('multiValidation', function () {
return function (scope, iElement, iAttrs) {
var parts = iAttrs.myvalidate.split(',');
scope.$watch('CustomerModel.Billable', function (val) {
if (scope.CustomerModel.Billable) {
angular.forEach(parts, function (part) {
var element = angular.element('[ng-model="CustomerModel.' + part + '"]');
scope.$watch('CustomerModel.' + part, function (value) {
if (value == null || value == "") {
scope.CustomerForm.$setValidity("CustomerForm", false);
element.addClass("ng-invalid ng-invalid-required");
}
else {
element.addClass("ng-valid ng-valid-required");
var validate = true;
angular.forEach(parts, function (part) {
if (scope["CustomerModel." + part ] == "")
validate = false;
});
scope.CustomerForm.$setValidity("CustomerForm", validate);
}
});
});
} else {
if (scope.CustomerModel.LastName == "" || scope.CustomerModel.LastName == null)
scope.CustomerForm.$setValidity("CustomerForm", false);
if (scope.CustomerModel.LastName != "" || scope.CustomerModel.LastName != null)
scope.CustomerForm.$setValidity("CustomerForm", true);
}
}, true);
};});
my problem is in the following line, I cannot access to the scope variable dynamically in custom directive.
scope["CustomerModel." + part ]
please guide me!!
the CustomerModel is also a variable of $scope. then I load CustomerModel form data base which it contains more property.
I can access to property of CustomerModel like following
$scope.CustomerModel.postalCode
the following way is wrong for dynamically access to them
scope['CustomerModel.postalCode']
the correct way is
scope['CustomerModel']['postalCode']
the whole of code is
app.directive('myvalidate', function () {
return function (scope, iElement, iAttrs) {
var parts = iAttrs.myvalidate.split(',');
scope.$watch('CustomerModel.billable', function (val) {
if (scope.CustomerModel.billable) {
angular.forEach(parts, function (part) {
var element = angular.element('[ng-model="CustomerModel.' + part + '"]');
scope.$watch('CustomerModel.' + part, function (value) {
if (value == null || value == "") {
scope.CustomerForm.$setValidity("CustomerForm", false);
element.addClass("ng-invalid ng-invalid-required");
}
else {
element.addClass("ng-valid ng-valid-required");
var validate = true;
angular.forEach(parts, function (p) {
if (scope['CustomerModel'][p] == "" || scope['CustomerModel'][p] == "undefined" || scope['CustomerModel'][p] == null)
validate = false;
});
if (scope.CustomerModel.customerLastName == "" || scope.CustomerModel.customerLastName == null) validate = false;
scope.CustomerForm.$setValidity("CustomerForm", validate);
}
});
});
} else {
if (scope.CustomerModel.customerLastName == "" || scope.CustomerModel.customerLastName == null)
scope.CustomerForm.$setValidity("CustomerForm", false);
if (scope.CustomerModel.customerLastName != "" || scope.CustomerModel.customerLastName != null)
scope.CustomerForm.$setValidity("CustomerForm", true);
}
}, true);
};
});
and the directive
<div class="panel-body" myvalidate="street,city">

ExtJs - column hide/show state save

I am trying to save state of grid columns,
I set
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
and configured grid with
stateful: true,
stateId: 'uniqueGridId',
Right now it saves everything about grid, even I do not have stateEvents.
How do I save only column hide / show state?
I tried
initStateEvents : function(){
this.colModel.on('hiddenchange', function(){ this.saveState; });
}
but nothing chages...
Anyway to save hide /show column state and only hide /show column state?
If somebody need it:
applyState: function(state) {
var cs = state.columns;
if (cs.length !== 0) {
for (var i = 0, len = cs.length; i < len; i++) {
var s = cs[i], c = Ext.getCmp(s.id);
if (typeof c !== "undefined") {
if (typeof s.hidden !== "undefined") {
c.hidden = s.hidden;
}
}
}
}
},

Resources