Свой быстрый фильтр

Добрый день! Подскажите пожалуйста как устроен быстрый фильтр. Т.к. пытаюсь создать что-то подобное в разделе "контрагенты" - в гриде, рядом с кнопками добавить..удалить создал 2 контрола:Edit(edtCode) и Button(btnSearch) - куда вводится код и после нажатия на кнопку должен отфильтроваться список контрагентов, вот скипт:

function btnSearchOnClick(Control) {
 var Dataset = BaseGridArea.GridDataset;
 Dataset.DisableEvents();
 var Code = edtCode.Value;
 ApplyDatasetFilter(Dataset, 'Code', Code, true);
 Dataset.Open();
 Dataset.EnableEvents();
 RefreshDataset(Dataset);
}

Но ничего не происходит. В чём может быть проблема? заранее спасибо!

Нравится

12 комментариев

скорее всего на BeforeOpen Вашего датасета отрабатывает функция
ApplyStandartWorkspaceFilter (название неточно)
нужно Ваш фильр накладывать после етой фн.

Судя по тому, где быстрый фильтр рисуется, он реализован в ядре.
DisableEvents() - EnableEvents() Лучше делать в try finally.
ApplyDatasetFilter, на сколько я понимаю, Dataset не трогает, тогда незачем и события отключать.
Dataset.Open() вроде бы ничего не делает, если датасет предварительно не закрыть.
Вобщем я бы это сделал так.

BaseGridArea.UseMyQuickFilter = false;
BaseGridArea.MyQuickFilterValue = '';
 
function btnSearchOnClick(Control) {
	var Dataset = BaseGridArea.GridDataset;
	var Code = edtCode.Value;
	BaseGridArea.UseMyQuickFilter = (Code != '');
	BaseGridArea.MyQuickFilterValue = Code;
	RefreshDataset(Dataset);
}
 
function dlDataOnDatasetBeforeOpen(Dataset, DoOpen) {
	edtCode.Value = BaseGridArea.MyQuickFilterValue; //Это нужно, чтобы не сбивать пользователей с толку, если случайно сотрут edtCode.Value, а btnSearch не нажмут
	ApplyDatasetFilter(Dataset, 'Code', BaseGridArea.MyQuickFilterValue,
		BaseGridArea.UseMyQuickFilter);
}

Upd: Действительно, это может не сработать, если ApplyStandardWorkspaceFilter отработает позже. Попробуйте, если не получится есть вариант UseMyQuickFilter и MyQuickFilterValue передавать через аттрибуты датасета и

ApplyDatasetFilter(Dataset, 'Code', Dataset.Attributes('MyQuickFilterValue'),
		Dataset.Attributes('UseMyQuickFilter'));

вызывать в скрипте датасета или раздела

Спасибо! А что это за методы такие: 'MyQuickFilterValue', 'UseMyQuickFilter' - я их не в датасете ни в BaseGridArea не нашёл...

Это не методы, это поля в BaseGridArea и аттрибуты в Dataset.
BaseGridArea это JS - объект и в нем вы можете создавать какие угодно поля (т.е. напишите в одном месте BaseGridArea.MyValue = 48 и в любом другом месте этого скрипта BaseGridArea.MyValue вернет 48).
Dataset.Attributes это тоже объект и в нем вы так же можете хранить свои значения. Только это объект, реализованый в ядре tscrm и в нем нельзя писать Attributes.MyValue = 48, нужно писать Attributes('MyValue') = 48.

Ни так ни так не работает :((((((((
Разве что получается если закоментировать

function dlAccountsOnDatasetBeforeOpen(Dataset) {
	var IsInSingleRowMode = GetIsInSingleRowMode();
	if (IsInSingleRowMode != true) {	
//		ApplyStandardWorkspaceFilter();		
	}
}

но она находится не в скрипте грида, а в scr_AccountsWorkspace

замените фн ApplyStandardWorkspaceFilter на свою
например такую

function ApplyMyWorkspaceFilter() {
  ApplyStandardWorkspaceFilter();
  ApplyDatasetFilter(Dataset, 'Code', BaseGridArea.MyQuickFilterValue,
                 BaseGridArea.UseMyQuickFilter);
}
 
 
function dlAccountsOnDatasetBeforeOpen(Dataset) {
        var IsInSingleRowMode = GetIsInSingleRowMode();
        if (IsInSingleRowMode != true) {       
              ApplyMyWorkspaceFilter();        
        }
}

Нуда, это то о чем я писал. Но так делать низзя. Делать нужно так

BaseGridArea.UseMyQuickFilter = false;
BaseGridArea.MyQuickFilterValue = '';
 
function btnSearchOnClick(Control) {
        var Dataset = BaseGridArea.GridDataset;
        var Code = edtCode.Value;
        BaseGridArea.UseMyQuickFilter = (Code != '');
        BaseGridArea.MyQuickFilterValue = Code;
        RefreshDataset(Dataset);
}
 
function dlDataOnDatasetBeforeOpen(Dataset, DoOpen) {
        edtCode.Value = BaseGridArea.MyQuickFilterValue; //Это нужно, чтобы не сбивать пользователей с толку, если случайно сотрут edtCode.Value, а btnSearch не нажмут
        ApplyDatasetFilter(Dataset, 'Code', BaseGridArea.MyQuickFilterValue,
                BaseGridArea.UseMyQuickFilter);
//Вот эта строка не даст отключится фильтру. Извиняюсь, что некрасиво, просто нет времени. Но работать будет
        Dataset.SelectQuery.Items(0).Filters.Items(0).ItemsByCode('Code').CanDisable = !BaseGridArea.UseMyQuickFilter;
}

"Березович Сергей" написал:замените фн ApplyStandardWorkspaceFilter на свою
например такую

Так делать не желательно. Иначе в деталях, где используется этот же грид будут нефункциональные кнопка и эдит. Их конечно можно прятать. Но по-моему мой вариант лучше. Выносить логику контролов, реализованых в одном окне, в другое как-то не солидно.

Спасибо! Вот только странно себя ведёт последняя строка , а именно:

Dataset.SelectQuery.Items(0).Filters.Items(0).ItemsByCode('Code').CanDisable 

при первом входе в раздел ругается, подходит только:

Dataset.SelectQuery.Items(0).Filters.ItemsByCode('Code').CanDisable 

, но если нажать на стандартную кнопку грида "обновить", то ругается на последнюю строку, тут ей первую подавай...

"_" написал:Так делать не желательно. Иначе в деталях, где используется этот же грид будут нефункциональные кнопка и эдит. Их конечно можно прятать. Но по-моему мой вариант лучше. Выносить логику контролов, реализованых в одном окне, в другое как-то не солидно.

почему нежелательно?
заменить фн ApplyStandardWorkspaceFilter чтобы накладывать фильтр в разделе
+ проверять если есть атрибут ParentID значить деталька
и значить накладывать фильтры в гриде детальки

"Березович Сергей" написал:почему нежелательно?

Потому что мухи должны быть отдельно, а котлеты отдельно. По возможности :) Ну и повторять одну и ту же логику в двух местах - китайский копипейст получается.

"Serega" написал:но если нажать на стандартную кнопку грида "обновить", то ругается на последнюю строку, тут ей первую подавай...

Что-то они творят с фильтрами в главном датасете раздела. Я попробовал запоминать этот фильтр в OnPrepare грида, так в OnPrepare мы имеем фильтр с одним InstanceID, а когда в ApplyDatasetFilter включаем IsEnabled, так у фильтра другой InstanceID. Получается они убивают Кенни, т.е старый фильтр и создают новый причем на уровень ниже. Будем думать.

Придумал.В scr_DB добвляем фунцкцию (делаем по подобию EnableFilter, но не ищем в подзапросах - лень, но в данном случае покатит).

function GetFilter(FiltersNode, FilterCode){
 
	if (FiltersNode.Code == FilterCode) {
		return FiltersNode;
	}
	var Result = null;
	if (FiltersNode.FilterType == ftFilters) {
		for (var i = 0; (i < FiltersNode.Count) && (!Assigned(Result)); i++) {
			Result = GetFilter(FiltersNode.Items(i), FilterCode);
		}
	}
	return Result;
}

В scr_AccountsGridArea пишем

function wnd_AccountsGridAreaOnPrepare(Window) {
	//...
	//Оставляем все как есть, просто дописываем в конец
	var Dataset = dlData.Dataset;
	Dataset.Attributes('UseMyQuickFilter') = false;
	Dataset.Attributes('MyQuickFilterValue') = '';
}
 
function dlDataOnDatasetBeforeOpen(Dataset, DoOpen) {
	edtCode.Value =  Dataset.Attributes('MyQuickFilterValue') ; //Это нужно, 
	// чтобы не сбивать пользователей с толку, если случайно сотрут 
	//edtCode.Value, а btnSearch не нажмут
	ApplyDatasetFilter(Dataset, 'MyQuickFilter', 
	Dataset.Attributes('MyQuickFilterValue'),
		Dataset.Attributes('UseMyQuickFilter'));
	var Filter = GetFilter(Dataset.SelectQuery.Items(0).Filters, 
		'MyQuickFilter');	
	Filter.CanDisable = !Dataset.Attributes('UseMyQuickFilter');	
}
 
function btnSearchOnClick(Control) {
	var Dataset = BaseGridArea.GridDataset;
	var Code = edtCode.Value;
	Dataset.Attributes('UseMyQuickFilter') = (Code != '');
	Dataset.Attributes('MyQuickFilterValue') = Code;
	RefreshDataset(Dataset);
}

В scr_AccountsWorkspace можно писать, а можно и не писать. Ядровый быстрый фильтр не сбрасывается при переходе в раздел из грида. Как по мне - лажа. Если мы хотим чтобы наш сбрасывался, то пишем так.

function dlAccountsOnDatasetBeforeOpen(Dataset) {
	var IsInSingleRowMode = GetIsInSingleRowMode();
	if (IsInSingleRowMode != true) {
		ApplyStandardWorkspaceFilter();
	} else {
		var Filter = GetFilter(Dataset.SelectQuery.Items(0).Filters, 
			'MyQuickFilter');
		Filter.CanDisable = true; 
		Filter.IsEnabled = false; 
	}
	//(IsInSingleRowMode == true) это отдельная песня. По хорошему за такое убивать надо, но GetIsInSingleRowMode может вернуть.... строку!!! :) 
	//...
	//дальше оставляем все как есть
}

Не получилось таки мух толком отделить (если делать изменения в scr_AccountsWorkspace) :) Фильтр и параметр я назвал 'MyQuickFilter'. Фильтр сдетал типа Like, в комбобоксе выбрал 'Содержит'. btnSearch нужно, наверное, сделать IsDefault = true, для удобства.

Вот, вроде сделали. Остался только маленький вопрос - зачем :)

Показать все комментарии