Skip to content

Instantly share code, notes, and snippets.

@MatteoOreficeIT
Created May 29, 2018 11:12
Show Gist options
  • Save MatteoOreficeIT/0c5865848c24b8293c2d96d413dba4b6 to your computer and use it in GitHub Desktop.
Save MatteoOreficeIT/0c5865848c24b8293c2d96d413dba4b6 to your computer and use it in GitHub Desktop.
Telerik Kendo grid checkbox mvvm binding to model
/**
* La variabile $checkedField che vedi riferita arriva da una variabile lato server che contiene
* il nome della colonna da utilizzarsi per settare in automatico il campo del model sul checkbox click
*
* Puo anche valere null o false, in quel caso il valore Javascript deve corrispondere a null o false, per
* fare questo in php si usa il metodo json_encode
*/
/**
* Determina quale e' la colonna tenuta in sync con la checkbox
* @type {string}
*/
var // QUESTA ASSEGNAZIONE va convertita correttamente in .NET perche se checkedField == false|null
// dataBindCheckField deve essere == null o false
dataBindCheckField = '$checkedField' // oppure false/null
;
grid.one('dataBound', function __customEventAnd(e) {
var grid = e.sender,
CHECKBOXINPUT = 'td[data-role=rowselectcheckbox] input[data-role=checkbox]',
CLICK = 'click',
SELECTED = 'k-state-selected',
NS = '.hasrowselection',
// righe selezionate nello stato precedente
// contiene tutte le righe anche se e'presente
// la paginazione
selectedRows = {},
multiple = $multiple;
/**
* Permette di salvare un elenco di model visualizzati durante la paginazione
*
* @param model
*/
grid.setModelIdImpressions = function (model) {
this._bitiaModelIdImpressions = this._bitiaModelIdImpressions || {};
this._bitiaModelIdImpressions[model[model.idField]] = true;
};
/**
* Recupera le impressions dei model, in questo modo si puo sarepere
* quali model sono stati VISTI
*
* @returns {*|{}}
*/
grid.getModelIdImpressions = function () {
return this._bitiaModelIdImpressions = this._bitiaModelIdImpressions || {};
};
if (dataBindCheckField) {
function setUserModelField(modelId, field, value) {
grid._bitiaModelsUserModifiedFields = grid._bitiaModelsUserModifiedFields || {};
grid._bitiaModelsUserModifiedFields[modelId] = grid._bitiaModelsUserModifiedFields[modelId] || {};
grid._bitiaModelsUserModifiedFields[modelId][field] = value;
}
// registra handler on click
grid.wrapper.on(CLICK + NS, 'tbody > tr ' + CHECKBOXINPUT, $.proxy(function (e) {
var that = this,
input = $(e.target);
row = input.closest('tr'),
uid = row.attr(kendo.attr('uid')),
checked = input.is(':checked'),
model = that.dataItem(row),
idField = model.idField,
idValue = model[idField]
;
if (!idField && console) {
throw new Error('Cannot save user selection, no model id has been assigned.');
return false;
}
if (!idValue && console) {
throw new Error('Cannot save user selection, model id value is not valid.');
return false;
}
if (!multiple) {
throw new Error('codice non testato ancora, testare e rimuovere questa eccezione');
that._deselectCheckRows(that.select());
}
// lancia evento, le righe selezionate si possono recuperare tramite selectedKeyNames()
that.trigger('selectrow', {
target: row[0],
checked: checked
});
setUserModelField(idValue, dataBindCheckField, checked);
}, grid));
}
})
/**
* Questi eventi vengono agganciati solo se si vuole legate della checkbox al campo model in automatico
*/
if(dataBindCheckField) {
grid.one('dataBound', function __closure(e) {
var grid = e.sender,
CHECKBOXINPUT = 'input[data-role=checkbox]',
CLICK = 'click',
NS = '.hasrowselection',
SELECTED = 'k-state-selected';
if (!grid.getOptions().persistSelection) {
throw new Error('HasRowSelection need persistSelection must be set on current grid.');
}
// Al click su checkAll tiene allineato il campo sui models
// sfrutta codice Telerik per intrappolare click su checkbox in header
// @see kendo.web.js:55049 (v2017.3.1026)
grid.wrapper.on(CLICK + NS, 'thead > tr ' + CHECKBOXINPUT, $.proxy(function (e) {
var that = this,
row = $(e.target).closest('tr'),
isChecking = $(e.target).is(':checked')
;
// controlla che il click sia sulla stessa grid
if (that !== kendo.widgetInstance(row.closest('.k-grid.k-widget'))) {
return;
}
// per ogni item sulla pagina caricata aggiorna il flag
$.each(that.dataSource.view(), function (i, dataItem) {
if (dataItem.get('$checkedField') != isChecking) {
// se usassimo set verrebbero scatenati N eventi change uno per ogni
// model, quindi e' preferibile fare aggiornare la grid solo alla fine
// di tutti i set
this._set('$checkedField', isChecking);
this.dirty = true;
this.dirtyFields['$checkedField'] = true;
}
});
// aggiorna eventuali altri campi dipendenti
that.refresh();
}, grid));
})
grid.bind('dataBound', function _mvvmRebind(e) {
var grid = e.sender,
count = 0,
SELECTED = 'k-state-selected',
CHECKBOXINPUT = 'input[data-role=checkbox]',
checked = [];
grid.items().each(function () {
var dataItem = e.sender.dataItem(this);
var checkbox = $(this).find('td[data-role=rowselectcheckbox] ' + CHECKBOXINPUT).attr('data-bind', 'checked: $checkedField');
// fa il bind solo nella TD per evitare che altri campi vengano legati
kendo.bind(checkbox.closest('td'), dataItem);
// se campo sul model e' true aggiunge la classe selezionato
// poiche MVVM allinea input e non il TR padre
if (dataItem.get('$checkedField')) {
$(this).addClass(SELECTED);
count++;
// checked.push(this);
}
else {
$(this).removeClass(SELECTED);
}
// grid.select(checked);
// questo garantisce che se tutti sono selezionati verra marcato il checkAll
grid._persistSelectedRows();
// salva le impressions dei modelli al fine di conoscere esattamente
// gli id dei modelli che sono stati caricati, utile per effettuare
// cancellazioni parziali
grid.setModelIdImpressions(dataItem);
});
// ripristina la spunta checkAll poiche' se tutte sono selezionate
// il binding MVVM non simula un click utente.
grid.thead.add(grid.lockedHeader).find(CHECKBOXINPUT).prop('checked', count == grid.items().length);
});
grid.bind('dataBound', function _restoreUserChoices(e) {
// evita un loop di dataBound dopo i set compiuti nel ciclo sottostante
if (_restoreUserChoices.refreshInProgress) {
_restoreUserChoices.refreshInProgress = false;
return;
}
// solo se arrivo da una pagina precedente
if (typeof (_restoreUserChoices.previousPage) != 'undefined' &&
_restoreUserChoices.previousPage !== e.sender.dataSource.page()) {
var selectedKeys = e.sender._bitiaModelsUserModifiedFields,
checkedField = '$checkedField',
CHECKBOXINPUT = 'td[data-role=rowselectcheckbox] input[data-role=checkbox]',
SELECTED = 'k-state-selected';
// per ogni model in pagina ripristino la colonna
$.each(e.sender.dataSource.view(), function (idx, item) {
if (item && selectedKeys && item.idField && item[item.idField] &&
typeof (selectedKeys[item[item.idField]]) != 'undefined' &&
typeof (selectedKeys[item[item.idField]][checkedField]) != 'undefined') {
var checked = selectedKeys && selectedKeys[item[item.idField]][checkedField] ? true : false;
// evita un databound per ogni set
if (item.get(checkedField) != checked) {
item._set(checkedField, checked);
item.dirty = true;
item.dirtyFields[checkedField] = true;
}
}
});
_restoreUserChoices.refreshInProgress = true;
e.sender.refresh();
}
_restoreUserChoices.previousPage = e.sender.dataSource.page();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment