I am currently setting up a multi-step form where the input from one slider needs to effect the max of another. I can manually update the max using this.tabSchema.(tab-id).fields[0].rangeSliderOptions.max, but this doesn't change the UX at all. I can see in the console that max has been correctly updated, but the UX shows the old max.
Digging into the ion.RangeSlider documentation, I see that it has .update, .destroy, and .reset methods. However, these seem to require a function particular to jquery, .data(), in order to properly setup the slider object that you then call .update() upon. I do not see any documentation around this for use in Vue. Is there a known way to do this? If not, does anyone know a way around it?
ETA: With code requested. Here is the relevant bit of tabSchema. There are many more tabs in the tabSchema, but these are the relevant two:
tabSchema: {
"num1" : {
fields: [{
type: "rangeSlider",
rangeSliderOptions: {
type: "single",
grid: false,
min: 0,
max: 2000000,
step: 5000,
// from: 100000,
prettify_enabled: true,
prettify_separator: ",",
prefix: "$",
hide_min_max: false,
},
id: "num1In",
model: "num1Val",
required:true,
styleClasses:'col-xs-12 col-sm-10 slider-bar'
}]
},
"num2" : {
fields: [{
type: "rangeSlider",
rangeSliderOptions: {
type: "single",
grid: false,
min: 0,
// max: ,
step: 5,
// from: 0,
prettify_enabled: true,
prefix: "$",
hide_min_max: false,
},
id: "num2In",
model: "num2Val",
required:true,
styleClasses:'col-xs-12 col-sm-10 slider-bar'
}]
}
}
And here is the bit of code that validates each tab:
validateTab: function(num){
var $valid = false; // assume not valid until checks are passed
this.error = '';
//////////// other validation //////////
else if (num == "num1"){
$valid = (this.model.num1Val != "");
if(!$valid){
this.error = 'Please provide a valid purchase price';
} else {
this.tabSchema.num2.fields[0].rangeSliderOptions.max = this.model.num1Val;
}
}
}
Documentation for ion.RangeSlider (public methods at the bottom): https://github.com/IonDen/ion.rangeSlider
Documentation for Vue-form-generator rangeslider: https://icebob.gitbooks.io/vueformgenerator/content/fields/slider.html
Related
I am using Angular ui-grid and am pretty new at it. I receive an array of objects to render data for each row. Each object, hence each row , has a field change:false which marks whether any field on that row has been edited or not. I have kept this field visible : false on screen.
However, whenever any change is made to any column of any row, I want to set this field as change:true.
How can this be achieved on the change of a ui-dropdown field or any other field for that matter.
I have this as my changing column:
{ name: "carrier_influence_group", displayName: "Carrier influence group", enableCellEdit: true,
editableCellTemplate: 'ui-grid/dropdownEditor', type:'object', cellFilter: 'cigFilter', editDropdownValueLabel: 'name',
editDropownOptionsArray: [{ id: 10, name: 'Small' }, { id: 11, name: 'Medium' }, { id: 12, name: 'Large' }]
},
I tried looking for any options available. But couldn't find any way in official docs. Kindly suggest a way or some relevant links
You can use the afterCellEdit event for this.
$scope.gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
gridApi.edit.on.afterCellEdit($scope, function (rowEntity, colDef, newValue, oldValue) {
if (newValue !== oldValue) {
rowEntity['change'] = true;
}
});
});
Free jqgrid column is defined to use html5 number input type like
{ name: "amount", width: 62, template: "number",
formatter: "number", formatoptions: {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 4, defaultValue: '0.0000'},
editoptions: {
maxlength; 4
type: "number",
max: 9999
} },
It allows to enter numbers from keyboard greater than 9999.
max: 9999 affects only to entry using spinner.
How to fix this so that keyboard entry cannot exceed 9999 ?
testcase is at
http://jsfiddle.net/jhckz7rr/3/
It allows to manually enter numbers greater that 9999 into Amount column. How to restrict manual entry to 9999 ?
I tried also to use string max value max: '9999' but problem persists.
If input type is text, input respects maxlength value.
Try to use something like the following
{
name: "amount",
width: 62,
template: "number", // formatter: "number"
formatoptions: {
decimalSeparator: ",",
thousandsSeparator: " ",
decimalPlaces: 2,
defaultValue: "0,00"
},
editoptions: {
maxlength: 7,
type: "number",
max: "9999",
dataEvents: [
{
type: "blur",
fn: function (e) {
if (e.target.checkValidity()) {
$(e.target).removeClass("ui-state-error");
} else {
$(e.target).addClass("ui-state-error");
alert(e.target.validationMessage);
$(e.target).focus();
}
}
}
]
}
}
The above code calls checkValidity() method of <input type="number">. Of cause you need to include additional tests in the code like validation that e.target.checkValidity is a function (for the case of executing in old web browser) and some other. The above code just shows the main idea of validation which uses functionality of <input type="number">.
See the demo http://jsfiddle.net/OlegKi/jhckz7rr/8/, which works for both inline editing and form editing.
Create validation on input with jQuery.
Event listeners are attached on edit click, and removed on save click.
I used setTimeout, to be synchronized with free-jqgrid elements manipulation - as the proper solution will be to extend free-jqgrid functionality
function restrictMax(){
var max = parseFloat($(this).attr('max'))
var value = parseFloat($(this).val())
if($(this).val() > max){
$(this).val(max)
}
}
setTimeout(function(){
$('.fa-pencil').click(function(){ //click on edit
var thatParent = $(this).closest('tr')
setTimeout(function(){
thatParent.find('input[type="number"]').on('input',restrictMax)
},0);
})
$('.fa-floppy-o').click(function(){ //click on save
var thatParent = $(this).closest('tr')
setTimeout(function(){
thatParent.find('input[type="number"]').off('input',restrictMax)
},0)
})
},0)
http://jsfiddle.net/jhckz7rr/6/
I have built a dojo OnDemandGrid that has a couple columns that have editors (NumberTextBox, and FilteringSelect) so I can modify values in the grid. I have also added some validation on these columns to help make sure the values that are entered are correct. This all appears to be working fine and when I enter an invalid value I get an indication that the value is incorrect.
My problem is when I try to send this data back to the server. When I get the grid data with a ui.searchResultGrid.collection.data, any of the fields that are invalid have not been updated in the collection and still have their original values. My guess is that when the cell is updated and does a save it does its validation, and if that validation fails it doesn't update the collection. How can I tell that some cells have failed validation and have issues?
Here's how I'm defining my grid if it helps:
require(["dojo/_base/declare", "dgrid/OnDemandGrid", "dgrid/Keyboard", "dgrid/Selection", "dgrid/Editor",
"dgrid/extensions/ColumnResizer", "dgrid/extensions/DijitRegistry", "dijit/form/NumberTextBox",
"dijit/form/FilteringSelect", "dojo/_base/lang", "dojo/domReady!"],
function (declare, OnDemandGrid, Keyboard, Selection, Editor, ColumnResizer, DijitRegistry, NumberTextBox, FilteringSelect, lang) {
var CustomGrid = declare([OnDemandGrid, Keyboard, Selection, Editor, ColumnResizer, DijitRegistry]);
ui.searchResultGrid = new CustomGrid({
columns: {
newItemAmount: {
label: "# of New Item",
editor: NumberTextBox,
editorArgs: {
constraints: {
min: 0.0001,
max: 999.9999,
allowNegative: false,
places: 4
},
style: "width:90px;",
required: true
},
autoSave: true,
resizable: false,
sortable: false,
width: 100
},
newItemUnitId: {
label: "Unit of New Item",
editor: FilteringSelect,
editorArgs: {
style: "width:130px",
searchAttr: "name",
labelAttr: "name",
required: true
},
autoSave: true,
resizable: false,
sortable: false,
width: 140
}
},
selectionMode: "none",
cellNavigation: false,
}, "searchResultGrid");
});
From what I was able to find, you have to look at each cell you want to validate and check .element.widget.isValid() to see if that widget passes validation. I wrote a function to validate a grid with parameters:
grid - the grid to validate
cols - an array of strings of the column names to validate
function gridValid(grid, cols) {
for (var i = 0; i < grid.collection.data.length; i++) {
var rowId = grid.collection.getIdentity(grid.collection.data[i])
for (var c = 0; c < cols.length; c++) {
if (!grid.cell(rowId, cols[c]).element.widget.isValid()) {
return false;
}
};
}
return true;
}
and I called the function like this:
if (gridValid(ui.searchResultGrid, ["newItemAmount", "newItemUnitId"])) {
var toSave = ui.searchResultGrid.collection.data;
//TODO: save the grid data
}
This may not be the best way to validate the grid, but it appears to be working.
I have am currently using Dojo EnhancedGrid with Pagination, filtering and cell edition.
The problem is that in one page, I need to update another value when a cell is edited. When I update this value, I loose the cell selected so I need to click on the next cell to select it and modify it.
It is so not possible to do Enter / edit / enter / down / enter / edit (Excel like edition).
Here is a part of my code :
var store = new dojo.data.ItemFileWriteStore({'data':data});
var grid = new dojox.grid.EnhancedGrid({
id: 'grid',
store: store,
structure: structure,
columnReordering: true,
autoHeight: true,
autoWidth: true,
initialWidth: '100%',
escapeHTMLInData: false,
plugins: {
pagination: {
pageSizes: ["10", "25", "50", "All"],
description: true,
sizeSwitch: true,
pageStepper: true,
gotoButton: true,
maxPageStep: 4,
position: "bottom"
},
filter : {}
},
onStartEdit: function(inCell, inRowIndex)
{
item = grid.selection.getSelected()[0];
currentVal = item[inCell['field']][0];
},
doApplyCellEdit: function(inValue, inRowIndex, inAttrName) {
if(inValue != currentVal){
[...]
$.ajax(url, data, {
success:function(data, textStatus) {
val = parseInt(data["info"]);
if(!isNaN(val)) {
grid.store.setValue(item, 'info', val);
grid.update();
} else {
grid.store.setValue(item, 'info', 0);
grid.update();
}
}
});
}
}
});
dojo.byId("gridDiv").appendChild(grid.domNode);
grid.startup();
Do you see any solution to handle this ?
I too use an enhanced dojo grid, where I had a similar problem. I used this to reload the data right:
require(["dijit/registry"],function(registry) {
var grid = registry.byId('grid');
grid._lastScrollTop=grid.scrollTop;
grid._refresh();
});
With this you always should get the last row you manipulated, and eventually also the last selected one... .
After many research, I have found the following solution :
$.ajax(url, data, {
success:function(data, textStatus) {
val = parseInt(data["info"]);
if(!isNaN(val)) {
grid.store.setValue(item, 'info', val);
grid.update();
window.setTimeout(function() {
grid.focus.next();
}, 10);
} else {
grid.store.setValue(item, 'info', 0);
grid.update();
window.setTimeout(function() {
grid.focus.next();
}, 10);
}
}
});
The timer is needed because there is a short delay before grid update the thus loosing the focus.
I am trying to interact with a javascript api (bare in mind I have never done this before). An example of what I am attempting to work with is here:
SearchSpring.Catalog.init({
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
});
In the example I want to add a "backgroundFilter" to this with a value:
var cat="MyNewCategory";
cat.value="ANewValue;
How would I add this category and value to the backgroundFilters: listed above?
This is a very common framework initialization pattern when working with frameworks.
Your example code is passing a JavaScript Object {} as a parameter into a function () that is called init.
Taking out all definitions the pattern looks like this:
SomeFramework.frameworkFunction({});
In the above code the {} is an empty object used for initialization. There are two ways that you can work with that object in practice.
Regarding your first code snippet, you can add code into that 'object literal'.
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['My value']
},
Notice the added comma, this is an important tripping point. This may or may not fit your needs, depending on a few factors.
Regarding your second code snippet, you can apply members to JavaScript objects at runtime. What I mean is, your var cat can be added to the anonymous object-literal that is being passed in. Hard to say, but a simple concept. Here is how:
//Say this is initialized in some separate way. //There is a bug here I'll describe later.
var cat="MyNewCategory";
cat.value="ANewValue";
//Extract and name the initialization object. It is verbatim at this point.
var initObject = {
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
};
//Now we can add variables (and functions) dynamically at runtime.
initObject.cat = cat;
//And pass them into the framework initialization in a separated way.
SearchSpring.Catalog.init(initObject);
Now for the bug. I don't know the solution because I do not know what it is intended to do, but I can point out what is potentially incorrect.
var cat="MyNewCategory";
cat.value="ANewValue;
This code is: 1 creating a String Object called cat. 2 changing the value to a new string.
I do not think this is what you really want.
To add a new backgroundFilter, in the separated way above, it would be:
initObject.backgroundFilters.cat = ['A', 'B'];
//Line above would give you this type of definition within the initObject (at runtime):
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['A','B']
},
For this to work it will depend on what the framework is expecting regarding backgroundFilters.
Hope that helps.
All the best!
Nash
I don't quite understand - do you want to have the backgroundFilters categories as structured objects rather than plain strings? If you are in control of the entire API, you can do something like
...
backgroundFilters: {
category: [
new SearchSpring.Catalog.Category("Shirt"),
new SearchSpring.Catalog.Category("Shoes"),
new SearchSpring.Catalog.Category("MyNewCategory", "ANewValue")
],
department: 'Mens'
}
...