BootstrapVue table : sort by date and by string? - sorting

I am quite new to VueJS, and currently using BootstrapVue (latest version, v2.0.0), mostly its b-table feature. I load table items dynamically (from a JSON file), and one of my field (column) is a string, the other is a formatted date (dd/MM/YYYY). I would like be able to sort those dates like other string or number fields.
The doc mention the possibility to create custom sorting function, so I wrote one (as a global function, using moment.js as suggested) :
function sortDate(a, b, key) {
aDate = moment(a[key], 'DD/MM/YYYY')
bDate = moment(b[key], 'DD/MM/YYYY')
if (aDate.isValid && bDate.isValid) {
if (aDate < bDate) {
return -1
}
else if (aDate > bDate) {
return 1
}
else {
return 0
}
}
return null
}
I then integrate it to HTML b-table using the :sort-compare tag :
<b-table id="bh_table" :items="items" :fields="fields" :sort-compare="sortDate"></b-table>
The problem is that the regulat string-sorting is broken, and I am not sure how to fix it ? Should I create a global method that should detect column type, and sort accordingly ?
It seems to be the thing to do here, but I think it is quite counter-intuitive, getting possible duplicates (I have other table that contains number and dates, only dates, etc.)

You are not checking for which key is being sorted on. Also note a and b are the entire row data.
function sortDate(a, b, key) {
if (key !== 'myDateField') {
// `key` is not the field that is a date.
// Let b-table handle the sorting for other columns
// returning null or false will tell b-table to fall back to it's
// internal sort compare routine for fields keys other than `myDateField`
return null // or false
}
aDate = moment(a[key], 'DD/MM/YYYY')
bDate = moment(b[key], 'DD/MM/YYYY')
if (aDate.isValid && bDate.isValid) {
if (aDate < bDate) {
return -1
}
else if (aDate > bDate) {
return 1
}
else {
return 0
}
}
return null
}

Related

How to check record is fully empty on left join in jooq query

I try to fetch a record from table with left join on another table. An information in the second table can be not found but I expect an information from the first table.
val citizenship = Tables.COUNTRIES.`as`("citizenship")
try {
return context.selectFrom(Tables.CLIENT_PROJECTIONS
.leftJoin(citizenship).on(
Tables.CLIENT_PROJECTIONS.CITIZENSHIP_COUNTRY_CODE.eq(
citizenship.CODE_ALPHA2
)
)
).where(Tables.CLIENT_PROJECTIONS.ID.eq(id)).fetchOne {
val clientProjection = ClientProjectionMapper.map(it.into(Tables.CLIENT_PROJECTIONS)) ?: return#fetchOne null
clientProjection.citizenship = CountryMapper.map(it.into(citizenship))
clientProjection
}
} catch (ex: DataAccessException) {
logger.error("Failed to access to database", ex)
throw ex
}
I convert data from CountriesRecord to Entity in CountryMapper:
object CountryMapper : RecordMapper<CountriesRecord, Country> {
override fun map(record: CountriesRecord?): Country? = when {
record != null -> {
Country(
countryCode = record.codeAlpha,
title = record.title
)
}
else -> {
null
}
}
}
But if query returns null in every fields of CountriesRecord my map method receive a non-nullable entity but everyone fields of this entity is empty.
I can check every field of CountriesRecord is it null but i think that isn't good idea. Can I check it by another more best way? May be I should write more correct query to database?
A LEFT JOIN in SQL does exactly that. It produces nulls for all columns of the left joined table for which there was no match in the join's ON clause.
You don't have to check whether each column is null. The primary key will be good enough, because that should have a NOT NULL constraint on it, meaning that if the primary key value is null (record.codeAlpha), then that must be because of the LEFT JOIN.
Change your second mapper to this:
object CountryMapper : RecordMapper<CountriesRecord, Country> {
override fun map(record: CountriesRecord?): Country? = when {
record?.codeAlpha != null -> {
Country(
countryCode = record.codeAlpha,
title = record.title
)
}
else -> {
null
}
}
}

Magento grid, getting incorrect total value

I created a grid. Issues is i am getting total number of records incorrectly. But all the records are in the grid.
I tried in grid.html $this->getCollection()->getSize() code and it returns the incorrect value.
But count($this->getCollection()) returns the correct value. How can i solve this issues with $this->getCollection()->getSize().
Can anyone help me please.
Thank You
This is the classic case of using a group by clause or a having clause (or both) on your collection. Magento's getSelectCountSql function does not account for the group by or the having clause because of its poor frontend performance. Instead it generally uses indeces and statistics. However, if you would like to you can override your collection's getSelectCountSql as follows:
public function getSelectCountSql($select) {
$countSelect = clone $select;
$countSelect->reset(Zend_Db_Select::ORDER);
$countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
$countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
if ($select->getPart(Zend_Db_Select::HAVING)) {
//No good way to chop this up, so just subquery it
$subQuery = new Zend_Db_Expr("(".$countSelect->__toString().")");
$countSelect
->reset()
->from(array('temp' => $subQuery))
->reset(Zend_Db_Select::COLUMNS)
->columns('COUNT(*)')
;
} else {
$countSelect->reset(Zend_Db_Select::COLUMNS);
// Count doesn't work with group by columns keep the group by
if (count($select->getPart(Zend_Db_Select::GROUP)) > 0) {
$countSelect->reset(Zend_Db_Select::GROUP);
$countSelect->distinct(true);
$group = $select->getPart(Zend_Db_Select::GROUP);
$countSelect->columns("COUNT(DISTINCT ".implode(", ", $group).")");
} else {
$countSelect->columns('COUNT(*)');
}
}
return $countSelect;
}
This should return the correct number from getSize

optimizing search query with criteria combination

i have a list of search inputs ( 4 search inputs ) , as criteria i have to do a combination to get a list of books ( by author , by publish date , by name , by number of pages )
this is the code
if((author!="") && (date!="")&&(name!="")&&(numPages!="")){
//query getting the books with th 4 criteria
}else{ if((author!="") &&(name!="")&&(numPages!="") ){
//query getting the books with th 3 criteria
}
} etc
is there a better way to do the combination of those criteria
EDIT
this is one of the queries with criteria :
def invoiceListbyAll=Invoice.createCriteria().list {
eq("author", authorObj)
eq("name", name)
eq("numPages", numPages)
}
You could write it as:
def invoiceListbyAll=Invoice.createCriteria().list {
// from your code I assume that all parameter are strings
if (author) { // groovy empty strings act as boolean false
eq("author", authorObj)
}
if (name) {
eq("name", name)
}
if (numPages) {
eq("numPages", numPages)
}
}

Need a CouchDB trick to sort by date and filter by group

I have documents with fields 'date' and 'group'. And this is my view:
byDateGroup: {
map: function(doc) {
if (doc.date && doc.group) {
emit([doc.date, doc.group], null);
}
}
}
What would be the equivalent query of this:
select * from docs where group in ("group1", "group2") order by date desc
This simple solution is not coming into my head. :(
Pankaj, switch the order of the key you're emitting to this:
emit([doc.group, doc.date], doc);
Then you can pass in a start key and an end key when querying the view. It might be easier to do a separate query for each group that you want to pull data for. The data will be sorted by date.
I'm on my way out at the moment, but can elaborate more when I get back if it isn't clear.
why not?
function(doc) {
if (doc.date && ["group1", "group2"].indexOf(doc.group) !== -1)) {
emit([doc.date, doc.group], null);
}
}
You need a specific view for this:
byDateGroup1Group2: {
map: function(doc) {
if (doc.date && doc.group && (doc.group === "group1" || doc.group === "group2") {
emit(doc.date, doc);
}
}
}
that you query (presumably in a list function) with query descending=true.

Custom Grails validation

I would like to check to make sure two fields are not equal and one is greater then the other. Say yearBorn and yearMarried. They cannot be equal and yearMarried must be greater then yearBorn.
You can use a 2-parameter custom validator that has access to both the value being validated and the entire instance:
static constraints = {
yearMarried validator: { year, instance ->
if (year == instance.yearBorn) {
return 'i18n.code.for.equal.value'
}
if (year <= instance.yearBorn) {
return 'i18n.code.for.born.after.married'
}
}
}

Resources