Предположим, есть два списка: «Проекты» и «Задачи». В списке "Задачи" есть поле "проект" типа подстановка. В это поле попадают названия проектов из списка "Проекты".
Идея состоит в том, что бы вывести на страницу DispForm.aspx веб-часть со списком «Задачи» и отфильтровать его по нужному проекту.
Попытка использовать самописную веб-чать фильтр (на основе интерфейса ITransformableFilterValues) провалилась . Веб-часть фильтра работает корректно, но не на странице DispForm.aspx.В этом случае веб-чать выводящая список к которой проводится подключение фильтра выводит следующий текст:
"Ошибка веб-части: На этой странице превышен порог получения данных для присоединенных веб-частей. Попробуйте отсоединить одну или несколько веб-частей."
Описанное решение использует только JavaScript, ни каких других изменений не требуется.
Веб-части списков поддерживают передачу параметров фильтрации через URL.
При открытии страницы DispForm.aspx с помощью JavaScript мы будем добавлять в URL необходимые параметры.
Прежде всего, напишем объект помогающий работать с GET-параметрами
LocationHelper = function() { }
LocationHelper.prototype = {
_GetParams: function(value) {
var crumbs, crumb, hash = {};
crumbs = value.split('&');
for (var i = 0; i < crumbs.length; i++) {
if (crumbs[i] === '')
continue;
crumb = crumbs[i].split('=', 2);
crumb[0] = decodeURIComponent(crumb[0]);
if (crumb.length == 0)
crumb.push('');
else
crumb[1] = decodeURIComponent(crumb[1]);
crumb[1] = crumb[1].split(',');
hash[crumb[0]] = crumb[1];
}
return hash;
},
ParamsToStr: function(params) {
var str = '';
for (var prop in params) {
if (params.hasOwnProperty(prop)) {
str = str + '&' + prop + '=' + params[prop];
}
}
return str.slice(1);
},
GetParams: function(str) {
var hash = {};
if (str == undefined || str == null) {
hash = this._GetParams(
window.location.search.replace('?', ''));
}
else if (str.indexOf('?') > 0) {
hash = this._GetParams(str.replace(/^[\s\S]*[?]/, ''));
}
return hash;
},
ChangeParams: function(params) {
var s = '?' + this.ParamsToStr(params);
if (window.location.search != s) {
window.location.search = s;
}
},
AddParams: function(params) {
var curParams = {};
if (window.location.search !== '') {
curParams =
this._GetParams(
window.location.search.replace('?', ''));
}
for (var prop in params) {
if (params.hasOwnProperty(prop)) {
curParams[prop] = params[prop];
}
}
this.ChangeParams(curParams);
}
}
Вот так его можно использовать:
var LHelper = new LocationHelper();
var params = LHelper.GetParams();
alert(params['ID']);
Ссылка для фильтра имеет следующий вид:
FilterField1=%5Fx041f%5F%5F…F%5Fx0435%5F%5Fx04&FilterValue1=%D0%91%D0%95%...
Где FilterField1 это поле по которому производится фильтрация, а FilterValue1 это значение фильтра.
Что бы получить FilterField1 сделайте фильтрацию списка вручную и скопируйте соответствующую строку из адресной строки браузера.
FilterValue1 (для данной задачи) это название проекта. Следующий простенький скрипт поможет получить строковое значение поля списка, если будет размещен на странице со стандартной формой просмотра элемента.
var GetListItemValue = function(fieldName) {
// mootools needed
var trs = $$('table.ms-formtable')[0].getElements('tr');
var value = null;
for (var i = 0; i < trs.length; i++) {
var h3 = trs[i].getElements('h3.ms-standardheader')[0];
if (h3.get('text').clean() == fieldName) {
value =
trs[i].getElements('td.ms-formbody')
.get('text').toString().clean();
break;
}
}
return value;
}
Для работы скрипта требуется JavaScript библиотека mootools.
Собирем все вместе. Разместите на странице DispForm.aspx веб-часть с дочерним списком «Задачи».
Добавить веб-часть на страницу DispForm.aspx можно, если ввести в адресную строку javascript:MSOTlPn_ShowToolPane('2') и нажать ентер (я себе сделал закладку).
Между двумя этими веб-частями разместите веб-часть редактора содержимого со следующим кодом:
<script src="/CustomControls/mootools-1.2.2-core-yc.js" type="text/javascript"></script>
<script type="text/javascript">
var GetListItemValue = function(fieldName) {
// Код см. выше
…
}
LocationHelper = function() { }
LocationHelper.prototype = {
// Код см. выше
…
}
var filterVal = GetListItemValue('Название');
var LHelper = new LocationHelper();
if (filterVal != null) {
var hh = LHelper.GetParams();
hh['FilterField1'] = '%5Fx0…35%5F%5Fx04';
hh['FilterValue1'] =
encodeURIComponent(filterVal).replace('-', '%2D');
LHelper.ChangeParams(hh);
}
</script>
Теперь веб-часть со списком «Задачи» будет отфильтрована по текущему проекту. Однако, если кликнуть на какой-либо задаче и войти в форму её просмотра, после нажатия «Закрыть» пользователь будет перенаправлен не на ту страницу с которой пришел.
Такой эффект наблюдается только если на странице DispForm.aspx главного списка «Проекты» в урл уже есть параметр Source. Похоже, что это ошибка стандартной JS функции GoToLink, которая вызывается когда вы кликаете на названии элемента списка.
Что бы побороть это явление, сразу за веб-частью выводящую список «Задачи» разместите еще одну веб-часть редактора содержимого:
<script type="text/javascript">
var MyGoToLink = function() {
var pp = LHelper.GetParams(this.href);
pp['Source'] = encodeURIComponent(window.location.href);
window.location.href = this.href.replace(/[?][\s\S]*$/, '')
+ '?' + LHelper.ParamsToStr(pp);
return false;
}
var aa = $$('a');
for (var i = 0; i < aa.length; i++) {
var js = aa[i].get('onclick');
if ($chk(js)) {
if (js.toString().contains('GoToLink(this);return false;')) {
aa[i].removeProperty('onclick');
aa[i].addEvent('click', MyGoToLink);
}
}
}
</script>