Detecting valid field on cellEdit - javascript

this should be pretty easy just can't find the answer in the documentation. So I'm using jQuery Tabulator and creating an error message when a rule is broken. Easy enough.
validationFailed:function(cell, value, validators){
$('#data-errors').html('<span class="error error-message">....</span>')
},
I want to remove that error message once the error is fixed but I can't see how to do it. I assume there is a really simple callback that I could run in the cellEdited function, a cellEdited callback sort of thing, or validate the entire table like how other validate plugins work:
if($('#data-table').valid()){ ... }
I just can't find it in the documentation:)

The cellEdited callback will be called if a cell passes validation and has been successfully edited.
You can either bind to this for the table as a whole
var table = new Tabulator("#example-table", {
cellEdited:function(cell){
//cell - cell component
},
});
or if you only want to monitor a specific column you can set it in a column definition:
{title:"Name", field:"name", cellEdited:function(cell){
//cell - cell component
},
}

Related

Custom and first options in ember-power-select

I'm using Ember-power-select-with-create to make custom selections possible in my dropdowns.
This is the power-select part in the .hbs file.
{{#power-select-multiple-with-create
options=options //array for prefill values
selected=offer.offer //is where we save it to (offer is the model and has an array named offer)
onchange=(action (mut offer.offer)) //default onchange for prefill options
onfocus=(action "handleFocus")
onblur=(action "handleBlur")
oncreate=(action "createOffer" offer.offer) //This calls "createOffer"
buildSuggestion=suggestion
as |offer|}}
{{offer}}
{{/power-select-multiple-with-create}}
The "createOffer" function in my .js file looks like this:
It gets two values passed: selected which is offer.offer and searchText which is the input that the user is trying to add.
createOffer(selected, searchText)
{
if (selected == null)
{
selected = []; //This is what I'm currently trying: if its null initialize it
}
if (selected.includes(searchText)) { //Don't add if it's already added
this.get('notify').alert("Already added!", { closeAfter: 4000 });
}
else { // if it's not yet added push it to the array
selected.pushObject(searchText);
}
}
This code works perfectly fine for adding those that we predefined as well for custom options, however it does not work if it is the first and a custom offer that we try to add to a new group of offers.
I'm assuming it has something to do with the fact that the array is not yet initialized. A pointer to the fact that it is due to the array not being initialized is that I get an error message along the lines of: Can't call pushObject on undefined. And I'm assuming the reason that it works with predetermined values is that ember-power-select probably initializes it somewhere but I couldn't find any documentation about it.
Thanks for your answers!
If anyone ever stumbles upon this, this was the solution
Calling that when we create the offer and then initializing the offer array like that:
offer.set('offer', []);

SAPUI5 Table: unbindRows & destroyColumns cause error: Cannot read property 'shouldRender' of undefined

I am using the Table object from the SAPUI5's sap.ui.table namespace:
var oTableOverview = new sap.ui.table.Table();
On rowSelectionChange, when selecting one row I populate another table, let's call it oTableDetail, that is filled with some data.
When deselecting the row from the first table, I want to clear the content of the second, and for that I use:
oTableDetail.destroyColumns();
oTableDetail.unbindRows();
When deselecting the row I get the following error:
TableRenderer.js:6 Uncaught TypeError: Cannot read property 'shouldRender' of undefined
I found the method shouldRender of the sap.ui.table.Column class, but I am not sure why would the cells be rerendered in this case.
I also noticed that if I use either oTable.destroyColumns(), or oTable.unbindRows() separately, the error does not appear.
I am using the "1.38.11" version of SAPUI5.
Can you please help me identify why this happens?
EDIT 1: A possible workaround would be to use:
oTableDetail.setModel(new sap.ui.model.json.JSONModel({}));
oTableDetail.destroyColumns();
Although I still don't know why the code mentioned before is not working.
EDIT 2: A behavior that I find a bit weird:
trying to add a setTimeout like this works (the error is not happening):
oTable.destroyColumns();
setTimeout(function(){ oTable.unbindRows(); }, 50);
but this other way it doesn't work (the error still appears) even if the delay is longer:
oTable.unbindRows();
setTimeout(function(){ oTable.destroyColumns(); }, 50);
var oTableOverview = new sap.ui.table.Table();
//your model with new dynamic data
var oModel = new sap.ui.model.json.JSONModel(newData);
oTableDetail.setModel(oModel);
//use rerender method which tries to replace
//its DOM reference by re-rendering with new data.
oTableDetail.rerender();
You don't need to actually delete columns or unbind rows.
Rerender method will take care of new data.
So if you don't want to set a new model, then just try to clean oData of an existing model.
var oTable = this.byId("oTable")
//your model with new dynamic data
var oModel = oTable.getModel();
oModel.setData(null);
// then if its needed, use updateBindings method to refresh
oModel.updateBindings();

Extjs 4.1 pagingtoolbar default page

I want to change default page of pagination toolbar to 1 of 1 instead 0 of 0 in case of no record.Plus I am not using store proxy to request any records, so is there any way to accomplish it without using store proxy. According to my requirement user can add rows manually to the grid with the pagination toolbar showing page 1 and when rows exceeds 10 it moves to 2nd page.
In Ext it is possible to overload a component like Ext.toolbar.Paging with your own custom version. Simply specify an alias in your definition and you can us it just like the "native control."
In order to be sure that the approach would work, I set up a test project with a simple datasource and implemented enough of a replacement definition that I could see the "Ext.toolbar.Paging".getPagingItems method being fired in my custom definition.
From that point you can replace the code inside the definition of the original method to allow for a custom minimum in addition to the opportunity to overload the "updateInfo" method to make sure that during data reloads you're not plowing through your customizations.
In addition to these two things, you should (with a relatively small amount of effort) be able to implement on top of the control to support dynamically changing it's values based on the contents of your grid.
If you look at the documentation for ux.data.PagingStore you should be able to suss out the differences in using a remotely supplied store from something that is served with data locally.
Hope this helps you.
Code Sample:
Ext.define(
"Test.view.testview.TvPageBar",
{
extend: "Ext.toolbar.Paging",
alias: "widget.tvpagebar",
title: "Bob",
strictInit: function () {
"use strict";
console.log("TvPageBar init");
},
getPagingItems: function () {
console.log("getPagingItems", this);
this.callParent(arguments);
},
initComponent: function () {
this.strictInit();
this.callParent(arguments);
}
}
);

How to (properly) render additional data in grid with RowExpander

I'm trying to render some data in the rowbody in a grid (with the RowExpander plugin).
My problem is that the ol' rowBodyTpl isn't enough for me as this data is from Records on Stores from the record being rendered (hmmm...).
Putting it simply: Every record of the grid has a store in it (lets call it Items). So, I want to render the record data and some data of the Items records aswell.
What would be the best(ish) way of doing so?
Override the renderer function of the rowexpander plugin, override the getAdditionalData, or none of these?
Thank you.
I know this question is a few years old, but here's a trick I currently use to handle this kind of situation. It takes advantage of "verbatim" blocks that XTemplates allow. These allow you to execute arbitrary code inside an XTemplate by wrapping it with {% ... %}. Inside those code blocks, this is set to the XTemplate itself. The XTemplate has an owner property that, in our case, references the RowExpander plugin itself, which, in turn, has a grid property to reference the grid. So, something like this allows you to add arbitrary data to the values passed into rowBodyTpl.
Ext.create('Ext.grid.Panel', {
...
injectRowBodyData: function(values) {
values.MyInjectedContent = "Here's some extra data!";
},
plugins: [
{
ptype: 'rowexpander',
rowBodyTpl: [
'{% this.owner.grid.injectRowBodyData(value); %}',
'<div>',
'<h1>{Title}</h1>',
'<p>{Content}</p>,
'<p>{MyInjectedContent}</p>',
'</div>'
]
}
]
});
Hhopefully Sencha will fix the plugin to provide a way to handle this in the future. But for now this works well. I tested this with v4.2.1.883, but this should work with any previous version of Ext 4. The only thing I can think of that may prevent it from working in the future is the XTemplate's owner property no longer being pointed to the plugin, or the plugin not having a reference to the grid with it's grid property.
How I "solve" this problem, it might help somebody else:
I overrode the getRowBodyFeatureData of the rowexpander plugin, as this function not only receives the data to be applied on the template, but also the record itself, so I just data added the extra stores/arrays from the record.
Not sure if its the best way, but hey... at least it works.
You can also use if else statements in rowBodyTpl:
Check for ":"
"<tpl if='phone == \":\"'>",
"<tpl else>",
"</tpl>"
Check for empty string
"<tpl if='phone == \"\"'>",
"</tpl>"
this sample is taken from here: link
This is how I usually do:
Ext.create('Ext.grid.Panel',{
border: true,
store: 'ds',
columns: []
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : ['<p><b>Title:</b>{name}<br/><b>Description:</b> {description}<br/><b>Experiment Design:</b> {experimentdesign}</p>']
}],
renderTo:
});

jQuery + TableSorter: Error when table is empty

jQuery's plugin TableSorter doesn't seem to handle a situation where it is attached to an empty table. Is there a neat way around this?
In my application the user can filter and search the data and eventually he or she will come up with a search criteria which doesn't return any values. In these situations it would be nice to "detach" the TableSorter or somehow fix it's code so that it works with an empty table.
I'm currently using the plugin like this:
$("#transactionsTable")
.tablesorter({ widthFixed: true, widgets: ['zebra'] })
.tablesorterPager({ container: $("#pager"), positionFixed: false });
This works well, until the table is empty. Then I get the following error:
Line: 3
Error: '0.length' is null or not an object
Any ideas? Is it possible to change the script so that the tablesorter is only added to the table if it has rows?
I think you can do it for your self.
if ($("#transactionsTable").find("tr").size() > 1)
{
//> 1 for the case your table got a headline row
$("#transactionsTable")
.tablesorter({ widthFixed: true, widgets: ['zebra'] })
.tablesorterPager({ container: $("#pager"), positionFixed: false });
}
If your table got a tbody tag it is easier:
if ($("#transactionsTable").find("tbody").find("tr").size() > 0)
This way is maybe not the most professional one, but it should work under this circumstatances.
The issue is related to the fact that several parts of the codebase use rows[0] to determine 1) total number of columns, 2) the parser type to use per column (eg "text" vs "digit").
Until this bug gets fixed, here is an easy workaround:
Create a fake row in each table with contents like ("fake", 123, 123, 123, "fake"). Note how my fake contents match the "type" of the column to avoid confusing the column type detector. <tr class="fake_row"><td>fake</td><td>123</td></tr>
Add CSS styling to make the fake row not render:
tr.fake_row {
display: none;
}
This seems to work effectively, allowing tablesorter to initialize and run error-free and has no impact on the rendered output.
A more generic approach would be to override the tablesorter plugin itself to check for empty tables (until they fix the issue). See this post on overriding jquery core methods: http://www.bennadel.com/blog/1624-Ask-Ben-Overriding-Core-jQuery-Methods.htm
(function () {
// Store a reference to the original tablesorter plugin.
var originalTableSorter = jQuery.fn.tablesorter;
// Define overriding method.
jQuery.fn.tablesorter = function () {
if (this.find('tbody tr').size() == 0) {
if (typeof console != "undefined" && console.log) {
console.log('skipping tablesorter initialization - table is empty');
}
return;
}
// Execute the original method.
originalTableSorter.apply(this, arguments);
}
})();
This has been fixed in the lastest tablesorter (see issue 95).
Since overwriting plugins is always a bad idea, here's a different approach: If you just want to make sure your data table contains actual data rows, the jQuery selector :has() gets the job done, too.
$('table.tablesorter:has(tbody tr)').tablesorter({
// your tablesorter config here
});

Categories

Resources