$(function () { BWA.DataGrid = BWA.DataGrid || {}; BWA.DataGrid.createViewWithDataGrid = $CommonViewDataGrid = function (params, viewInfo, dbModelId, options) { var mandatoryFields = options.mandatoryFields, handleBeforePopupShowingPromise = options.handleBeforePopupShowingPromise, isValidateWithFunction = options.isValidateWithFunction, isModifiable = _.isBoolean(options.isModifiable) ? options.isModifiable : undefined, //2015 11 17 hcLee //handleCustermInsert = options.handleCustermInsert, //useDeleteButton = options.useDeleteButton || true // hcLee 2015 03 06 -> useDeleteButton = (options.useDeleteButton == false) ? false : true;// hcLee 2015 03 06 <- //alert('option = ' + options.useDeleteButton); var initialized = false, initializedInPopup = false, isHidden = false, shouldReload = false, dataViewModel = new BemsWebApplication[dbModelId + 'ViewModel'](), backupDataViewModel = null, isNewInPopup = ko.observable(false), isEditModeInPopup = ko.observable(false), viewModeInPopup = ko.observable(true), visibleEditButton = ko.observable(true), visibleDeleteButton = ko.observable(true), visibleCancelButton = ko.observable(false), selectedId = {}, selectedData = ko.observable(), gridView = ko.observable(), popupVisible = ko.observable(false), dataSource, isUseSiteId = options.isUseSiteId, defaultFilter = ko.observable([]), popupInsertButtonOptions, hasnotModificationPermission; //alert(useDeleteButton); function handleModification() { shouldReload = true; } function showPopup(clickRowData) { if (handleBeforePopupShowingPromise) { var promise = handleBeforePopupShowingPromise(isNewInPopup, dataViewModel, clickRowData); if (_.isObject(promise)) { promise.done(function () { popupVisible(true); }); } else { popupVisible(true); } } else { popupVisible(true); } } function handleViewShown() { if (shouldReload) { shouldReload = false; refreshList(); //dataSource.pageIndex(0); //dataSource.load(); } if (initialized === false) { if (dataViewModel.SiteId != null) { defaultFilter(dataSource.filter()); if (_.isUndefined(defaultFilter()) && isUseSiteId !== false) { defaultFilter([['SiteId', '=', BWA.UserInfo.SiteId()]]); dataSource.filter(defaultFilter()); } } $.extend(options, { dxDataSource: dataSource, selectedSourceItem: dataViewModel, selectedId: selectedId, selectedData: selectedData, datagridId: 'gridContainer', popupVisible: popupVisible, handleShowPopup: showPopup, dbId: dbModelId }); if (options.useNumberColumn === undefined) { options.useNumberColumn = true; } $("#gridContainer").dxDataGrid(utils.datagrid.defaultOptions(options)); gridView($('#gridContainer').dxDataGrid('instance')); // initializedFunction(); initialized = true; } if (isHidden) { var grid = gridView(); if (grid.refresh) { grid.refresh(); } isHidden = false; } if (typeof options.handleViewShown === 'function') { options.handleViewShown(dataViewModel, isEditModeInPopup); } //$SearchView.isNotUse(true); //alert("viewShown"); } function handleViewDisposing() { BemsWebApplication.db[dbModelId].modified.remove(handleModification); } function handleViewHidden() { isHidden = true; if ($SearchView.visibleObservable != null && $SearchView.visibleObservable != undefined) // 2018 01 19 hcLee 방어코드 $SearchView.visibleObservable(false); // hcLee 2015 07 28 // 화면이 바뀌면 팝업되어있던 검색창은 닫는다. // //visiblePopup(false); } function handleViewShowing() { if (options.handleViewShowing) { options.handleViewShowing(dataViewModel); } //window.$SearchView.isNotUse(true); //BemsWebApplication.app.loadTemplates('views/sideMenu/sidemenu1.dxview'); //deferred.resolve(); } function refreshList() { //dataSource.pageIndex(0); //dataSource.load(); gridView().refresh(); } function handlePopupHiding(e) { if (options.handlePopupHiding) { options.handlePopupHiding(isNewInPopup); } } function handlePopupShowing(e) { //alert('handlePopupShowing'); //visibleDeleteButton(useDeleteButton); // hcLee 2015 03 04 //visibleDeleteButton(false); // hcLee 2015 03 04 visibleCancelButton(false); if (isNewInPopup() === false) { activePopupViewMode(); // hcLee 2016 02 14 if (_.isUndefined(options.handlePopupShowing2) === false) { options.handlePopupShowing2(selectedId); } BemsWebApplication.db[dbModelId].byKey(selectedId).done(function (data) { dataViewModel.fromJS(data); var handle = options.handleAfterLoadingModelByKey; if (typeof handle === 'function') { handle(data, dataViewModel, isNewInPopup, isEditModeInPopup, selectedData()); } }); } else { clearDataModelValue(dataViewModel); } if (_.isUndefined(options.handlePopupShowing) === false) { options.handlePopupShowing(isNewInPopup, dataViewModel, selectedData()); } } function handlePopupShown() { /* hcLee 2016 06 03 위로 이동 if (_.isFunction(options.checkPopupVisible)) { if (options.checkPopupVisible(isNewInPopup) === false) { popupVisible(false); return; } }*/ if (initializedInPopup === false) { if (_.has(options, 'handleInitializedInPopup')) { options.handleInitializedInPopup(); } initializedInPopup = true; } if (_.has(options, 'handlePopupShown')) { options.handlePopupShown(isEditModeInPopup(), isNewInPopup(), dataViewModel); } } function clearDataModelValue(v) { BWA.DataUtil.resetViewModel(v); if (isUseSiteId) v.SiteId(BWA.UserInfo.SiteId()); // if 문 추가 hcLee2015 03 06 var handleInitializeDataModelValue = options.handleInitializeDataModelValue; if (handleInitializeDataModelValue !== undefined) { handleInitializeDataModelValue(v); } } function handleConfirmDelete() { // hcLee 2015 07 16 --> if (options.handleBeforeDelete) { var promises = []; promises.push(options.handleBeforeDelete(selectedId)); $.when.apply(this, promises).done(function () { }); } // hcLee 2015 07 16 BemsWebApplication.db[dbModelId].remove(selectedId).done(function () { popupVisible(false); refreshList(); if (typeof options.handleAfterDelete === 'function') { options.handleAfterDelete(); } utils.toast.show('데이터베이스 항목 삭제 작업이 성공하였습니다.'); }); } function update_real(showToast) { showToast = showToast || true; //console.log( dataViewModel.BuildingId() ); var updatePromise = BemsWebApplication.db[dbModelId].update(selectedId, dataViewModel.toJS()); var anotherPromise = null; if (_.isFunction(options.handleSaveButtonInPopup)) { anotherPromise = options.handleSaveButtonInPopup(false); } var promise = $.when(updatePromise, anotherPromise); promise.done(function () { refreshList(); if (showToast) { utils.toast.show('데이터 수정 작업이 성공하였습니다.'); } if (options.handleSaveSuccess) { options.handleSaveSuccess(dataViewModel); } popupVisible(false); // 2016 09 29 hcLee 추가 if (typeof options.afterUpdateDataViewModel === 'function') { $.when(options.afterUpdateDataViewModel(dataViewModel)) .done(function (result) { //utils.toast.show(result, '정보'); }); } }) .fail(function () { // console.log(arguments); // utils.toast.show('데이터베이스 작업에 오류가 있습니다 : ' + arguments[2], 'error'); utils.toast.show('수정이 실패하였습니다. 필수입력사항(*)이 누락, 데이터 중복, 또는 입력글자수 초과 입니다.', 'error'); }); return promise; } function update(showToast) { if (typeof options.beforeUpdateDataViewModel === 'function') { $.when(options.beforeUpdateDataViewModel(dataViewModel)) .done(function (result, fMsg) { if (result == 1) { // 자체적으로 update를 하는 화면은 1을 리턴 //2016 01 06 beforeUpdateDataViewModel를 사용하는 화면은 현재 구매요청과 발주 2군데 이다. 둘다 자체적으로 update를 직접 하고 있다. //update_real(showToast); } else if (result == 2) { update_real(showToast); } else { utils.toast.show(fMsg, 'error'); return; } }); } else { update_real(showToast); } } // 필수 데이터 필드 이름 목록이 입력되어 있으면, 해당 필드값이 null 인지 검사한다. function isValidateMandatoryDataFields() { if (_.isArray(mandatoryFields)) { var mandatoryFieldName = null; var isValid = _.every(mandatoryFields, function (field) { var value = dataViewModel[field.dataField]; if (_.isFunction(value)) { value = value(); } if (!_.isNull(value) && !_.isUndefined(value)) { if (_.isString(value)) { if (_.isEmpty(value) === false) { return true; } } else { return true; } } mandatoryFieldName = field.name; return false; }); if (!isValid) { utils.toast.show('값을 입력해 주십시오: ' + mandatoryFieldName, 'error'); return false; } } return true; } // 외부 함수를 통해 값이 유효한지 검사한다. // dataViewModel 외에 다른 유효한 상황들이 있을 때 사용한다.(예: 구매요청 자재) function checkValidateFunction() { if (_.isFunction(isValidateWithFunction)) { var errorMessage = { message: '' }; if (!isValidateWithFunction(errorMessage)) { utils.toast.show('{0}: {1}'.formati($('error'), errorMessage.message), 'error'); return false; } } return true; } function handlePopupButtonSave() { if (isValidateMandatoryDataFields() === false) { return; } // 필수 입력 조건 체크는 각 화면의 옵션 beforeInsertingDataViewModel에서 각각 처리 하는 것을 권합니다. hcLee 2016 01 15 // -->> // 필수 입력 조건 체크 // cyim 2015.12.28 : 설정-시설관리-시설등록-설비정보관리 에서 설비 등록 팝업창의 입력 정보 체크 if (dbModelId == "CmFacility") { // 시설유형 if (BWA.DataUtil.isValidInputValue(dataViewModel.FacilityTypeId()) == false // 시설명칭 || BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false // 시설별칭 || BWA.DataUtil.isValidInputValue(dataViewModel.Nickname()) == false // 시설분류 || (BWA.DataUtil.isValidInputValue(dataViewModel.FirstClassId()) == false && BWA.DataUtil.isValidInputValue(dataViewModel.SecondClassId()) == false && BWA.DataUtil.isValidInputValue(dataViewModel.ThirdClassId()) == false)) { utils.toast.show($G('Error_CmFacility_NotInputData'), 'error'); return; } } // cyim 2015.12.29 : 설정-시설관리-회사부서관리-회사구분코드 에서 입력 정보 체크 else if (dbModelId == "CmCompanyType") { // 회사 if (BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false) { utils.toast.show($G('Error_CmCompanyType_NotInputData'), 'error'); return; } } else if (dbModelId == "BemsAlarmGroup") { if (BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false) { utils.toast.show($G('Error_BemsAlarmGroup_NotInputData'), 'error'); return; } } else if (dbModelId == "BemsAlarmGroupUser") { if (BWA.DataUtil.isValidInputValue(dataViewModel.SiteId()) == false || BWA.DataUtil.isValidInputValue(dataViewModel.UserId()) == false || BWA.DataUtil.isValidInputValue(dataViewModel.AlarmGroupId()) == false) { utils.toast.show($G('Error_BemsAlarmGroup_NotInputData'), 'error'); return; } } // cyim 2015.12.29 : 설정-시설관리-회사부서관리-회사정보관리 에서 입력 정보 체크 else if (dbModelId == "CmCompany") { // 회사명칭 if (BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false // 회사구분 || BWA.DataUtil.isValidInputValue(dataViewModel.CompanyTypeId()) == false // 회사대표 || BWA.DataUtil.isValidInputValue(dataViewModel.RepresentativeName()) == false // 대표번호 || BWA.DataUtil.isValidInputValue(dataViewModel.PhoneNo()) == false) { utils.toast.show($G('Error_CmCompany_NotInputData'), 'error'); return; } } //공사계획 else if (dbModelId == "FmsConstruction") { //공사명 if (BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false //공사위치 || BWA.DataUtil.isValidInputValue(dataViewModel.ConstructLocation()) == false //공사구분 || BWA.DataUtil.isValidInputValue(dataViewModel.ConstructionTypeId()) == false //공사상태 || BWA.DataUtil.isValidInputValue(dataViewModel.ProgressId()) == false //공사업체 || BWA.DataUtil.isValidInputValue(dataViewModel.PartnerId()) == false //공사업체 연락처 //|| BWA.DataUtil.isValidInputValue(dataViewModel.PartnerPhoneNo()) == false //책임자 || BWA.DataUtil.isValidInputValue(dataViewModel.OwnerShipName()) == false //작업자연락처 || BWA.DataUtil.isValidInputValue(dataViewModel.OwnerShipPhoneNo()) == false) { utils.toast.show('저장 혹은 수정 반드시 필수 입력 정보(*)를 모두 입력하셔야 합니다 (앞뒤공백 허용안함)', 'error'); return; } } else if (dbModelId == "CmCompany") { // 회사명칭 if (BWA.DataUtil.isValidInputValue(dataViewModel.Name()) == false // 회사구분 || BWA.DataUtil.isValidInputValue(dataViewModel.CompanyTypeId()) == false // 회사대표 || BWA.DataUtil.isValidInputValue(dataViewModel.RepresentativeName()) == false // 대표번호 || BWA.DataUtil.isValidInputValue(dataViewModel.PhoneNo()) == false) { utils.toast.show($G('Error_CmCompany_NotInputData'), 'error'); return; } } // <<--- // 필수 입력 조건 체크는 각 화면의 옵션 beforeInsertingDataViewModel에서 각각 처리 하는 것을 권합니다. hcLee 2016 01 15 // if (isNewInPopup()) { if (_.has(options, 'handleSaveInPopup')) { var promise = options.handleSaveInPopup(dataViewModel, popupVisible); if (promise) { promise.then(handleThenAfterInsert); } } else { insert(); } } else { update(); } } function handleThenAfterInsert(response, responseKey) { if (_.isFunction(options.handleSaveButtonInPopup)) { options.handleSaveButtonInPopup(true); } if (_.isFunction(options.handleAfterSaveInPopup)) { options.handleAfterSaveInPopup(responseKey, response); } refreshList(); popupVisible(false); // 2015 07 16 hcLee if (typeof options.handleAfterInsert === 'function') { options.handleAfterInsert(responseKey, response); } utils.toast.show('데이터베이스 항목 등록 작업이 성공하였습니다.'); } function insert_real() { BemsWebApplication.db[dbModelId].insert(dataViewModel.toJS()).done(handleThenAfterInsert) .fail(function () { utils.toast.show('등록이 실패하였습니다. 필수입력사항(*)이 누락 되었거나 중복된 데이터가 있습니다.', 'error'); }); } function insert() { if (typeof options.beforeInsertingDataViewModel === 'function') { // !!!!! hcLee 2015 11 18-19 결국 beforeInsertingDataViewModel 추가구현 필요, // beforeInsertingDataViewModel 는 Deferred로 구현되어져야 한다 !!!!! $.when(options.beforeInsertingDataViewModel(dataViewModel)) .done(function (result, fMsg) { if (result == true) { insert_real(); } else { utils.toast.show(fMsg, 'error'); } }); } else { insert_real(); } } function activePopupEditMode() { //visibleCancelButton( false ); // alert('activePopupEditMode'); visibleEditButton(false); visibleDeleteButton(false); viewModeInPopup(false); isEditModeInPopup(true); } function activePopupViewMode() { // alert('activePopupViewMode'); visibleEditButton(true); visibleDeleteButton(useDeleteButton); // 왜 이게 TRUE인가? //visibleDeleteButton(false); viewModeInPopup(true); isEditModeInPopup(false); } function handlePopupButtonEdit() { // hcLee 2016 02 01 if (_.has(options, 'handlePopupButtonEdit')) { options.handlePopupButtonEdit(dataViewModel); } // hcLee 2016 02 01 activePopupEditMode(); visibleCancelButton(true); backupDataViewModel = getBackupDataViewModel(dataViewModel); } function getBackupDataViewModel(model) { var object = {}; $.each(model, function (name, value) { if (ko.isObservable(value)) { object[name] = value(); } }); return object; } function restoreDataViewModelFromBackup(model, backupModel) { $.each(backupModel, function (name, value) { model[name](value); }); } function handlePopupButtonCancel() { activePopupViewMode(); visibleCancelButton(false); if (_.isFunction(options.handleCancelInPopup)) { options.handleCancelInPopup(dataViewModel, backupDataViewModel); } restoreDataViewModelFromBackup(dataViewModel, backupDataViewModel); } function popupInsertView() { // 2016 06 03 handlePopupShown에서 이곳으로 이동 hcLee if (_.isFunction(options.checkPopupVisible)) { if (options.checkPopupVisible(isNewInPopup) === false) { popupVisible(false); return; } } activePopupEditMode(); isNewInPopup(true); visibleEditButton(false); visibleDeleteButton(false); showPopup(); } function handlePopupButtonDelete() { DevExpress.ui.dialog.confirm($G('deleteConfirmMsg'), "삭제").then(function (result) { if (result) { handleConfirmDelete(); } }); } function handlePopupButtonClose() { // 팝업의 추가 버튼들 깜빡이는 문제 해결을 위해 확장한 2016 07 26 hcLee if (_.isFunction(options.handlePopupButtonClose)) { options.handlePopupButtonClose(dataViewModel, backupDataViewModel); } isNewInPopup(false); isEditModeInPopup(false); popupVisible(false); } popupVisible.subscribe(function (visible) { if (visible == false) { $.each(selectedId, function (name) { delete selectedId[name]; }); //clearDataModelValue(dataViewModel); isNewInPopup(false); // visibleEditButton(true); // hcLee 2016 01 19 //visibleDeleteButton(useDeleteButton); visibleDeleteButton(false); } }); //dataSource = $DataSource(options, dbModelId); dataSource = BWA.DataUtil.createDataSource(options, dbModelId); BemsWebApplication.db[dbModelId].modified.add(handleModification); var viewModel = BWA.CommonView.create(params, viewInfo, options, (options.NoSearch != undefined) ? null : ko.observable(null), // 2018 01 19 hcLee 검색버튼 다시 생기는 문제 처리 //options, ko.observable(null), handleViewShown, defaultFilter); // 2018 01 19 hcLee 검색버튼 다시 생기는 문제 처리 handleViewShown, defaultFilter); // 2018 01 19 hcLee hasnotModificationPermission = viewModel.hasnotModificationPermission; var toolbarItems, toolbarItems2; if (_.isUndefined(options.toolbarItemsInPopup)) { // isModifiable은 사용자 권한에 따라 바뀌는 것이 아니고, 설계된 화면 자체가 그렇게 생겼다는 의미다. toolbarItems = [ { location: 'before', text: $G('detailInfo') }, { location: 'after', widget: 'button', options: { text: $G('edit'), icon: 'edit', visible: _.isBoolean(isModifiable) ? isModifiable : visibleEditButton, disabled: hasnotModificationPermission, clickAction: handlePopupButtonEdit } }, { location: 'after', widget: 'button', options: { text: $G('delete'), type: 'danger', icon: 'remove', visible: _.isBoolean(isModifiable) ? isModifiable : visibleDeleteButton, disabled: hasnotModificationPermission, clickAction: handlePopupButtonDelete } }, { location: 'after', widget: 'button', options: { text: $G('cancel'), icon: 'cancel', visible: visibleCancelButton, clickAction: handlePopupButtonCancel } }, { location: 'after', widget: 'button', options: { text: $G('save'), icon: 'save', visible: isEditModeInPopup, disabled: hasnotModificationPermission, clickAction: handlePopupButtonSave } }, { location: 'after', widget: 'button', options: { text: $G('close'), icon: 'close', clickAction: handlePopupButtonClose } } ]; toolbarItems2 = [ { location: 'before', text: $G('detailInfo') }, { location: 'after', widget: 'button', options: { text: $G('edit'), icon: 'edit', visible: _.isBoolean(isModifiable) ? isModifiable : visibleEditButton, disabled: hasnotModificationPermission, clickAction: handlePopupButtonEdit } }, { location: 'after', widget: 'button', options: { text: $G('cancel'), icon: 'cancel', visible: visibleCancelButton, clickAction: handlePopupButtonCancel } }, { location: 'after', widget: 'button', options: { text: $G('save'), icon: 'save', visible: isEditModeInPopup, disabled: hasnotModificationPermission, clickAction: handlePopupButtonSave } }, { location: 'after', widget: 'button', options: { text: $G('close'), icon: 'close', clickAction: handlePopupButtonClose } } ]; if (_.isUndefined(options.getAddedToolbarItemsInPopup) === false) { toolbarItems.splice.apply(toolbarItems, [1, 0].concat(options.getAddedToolbarItemsInPopup({ // param 추가 : JDSONG isNewInPopup: isNewInPopup, isEditModeInPopup: isEditModeInPopup, hasnotModificationPermission: hasnotModificationPermission, dataViewModel: dataViewModel, popupVisible: popupVisible }))); } if (_.isUndefined(options.getAddedToolbarItemsInPopup) === false) { toolbarItems2.splice.apply(toolbarItems2, [1, 0].concat(options.getAddedToolbarItemsInPopup({ // param 추가 : JDSONG isNewInPopup: isNewInPopup, isEditModeInPopup: isEditModeInPopup, hasnotModificationPermission: hasnotModificationPermission, dataViewModel: dataViewModel, popupVisible: popupVisible }))); } } else { toolbarItems = options.toolbarItemsInPopup; toolbarItems.push({ location: 'after', widget: 'button', options: { text: $G('close'), icon: 'close', clickAction: handlePopupButtonClose } }); toolbarItems2 = options.toolbarItemsInPopup; toolbarItems2.push({ location: 'after', widget: 'button', options: { text: $G('close'), icon: 'close', clickAction: handlePopupButtonClose } }); } var popupOptions = { width: options.popupWidth || '680px', height: 'auto', //shading: false, shadingColor: 'rgba(0,0,0,0.0)', visible: popupVisible, closeOnOutsideClick: false, showingAction: handlePopupShowing, shownAction: handlePopupShown, hidingAction: handlePopupHiding, animation: params.popupAnimation || utils.popup.createAnimation() }; var popupOptions_floorplan = { width: options.popupWidth || '720px', height: '780px', //shading: false, shadingColor: 'rgba(0,0,0,0.0)', visible: popupVisible, closeOnOutsideClick: false, showingAction: handlePopupShowing, shownAction: handlePopupShown, hidingAction: handlePopupHiding, animation: params.popupAnimation || utils.popup.createAnimation() }; popupInsertButtonOptions = { icon: 'add', id: 'create', title: options.insertButtonText || $G('insert'), action: popupInsertView, visible: 'true', disabled: hasnotModificationPermission }; if (_.has(params, 'popupPosition')) { popupOptions.position = params.positions; popupOptions_floorplan.position = params.positions; } if (_.isFunction(options.contentReadyActionInPopup)) { popupOptions.contentReadyAction = options.contentReadyActionInPopup; popupOptions_floorplan.contentReadyAction = options.contentReadyActionInPopup; } if (_.isUndefined(params.popupPosition) === false) { popupOptions.position = params.popupPosition; popupOptions_floorplan.position = params.popupPosition; } if (_.isUndefined(params.shownActionInPopup) === false) { popupOptions.shownAction = params.shownActionInPopup; popupOptions_floorplan.shownAction = params.shownActionInPopup; } viewModel = $.extend(viewModel, { gridView: gridView, dataModel: dataViewModel, dataSource: dataSource, refreshList: refreshList, viewShowing: handleViewShowing, // viewShown: handleViewShown, viewHidden: handleViewHidden, viewDisposing: handleViewDisposing, popupInsertView: popupInsertView, viewModeInPopup: viewModeInPopup, isEditModeInPopup: isEditModeInPopup, isNewInPopup: isNewInPopup, popupOptions: popupOptions, popupOptions_floorplan: popupOptions_floorplan, popupVisible: popupVisible, toolbarItems: toolbarItems, toolbarItems2: toolbarItems2, handlePopupButtonClose: handlePopupButtonClose, visibleEditButton: visibleEditButton, visibleDeleteButton: visibleDeleteButton, popupInsertButtonOptions: popupInsertButtonOptions, update: update }); // 이 함수로 filter를 설정하면, SearchConditionView의 조건과 나중에 합산 된다. viewModel.setGridViewFilter = function (filter) { defaultFilter(filter); gridView().filter(filter); }; // SearchConditionView에서 검색 버튼을 클릭하면 호출된다. viewModel.promiseSearchEvent.progress(function (filter) { gridView().filter(filter); }); viewModel.handleExcelDownload = function () { }; viewModel.handlePopupButtonEdit = handlePopupButtonEdit; return viewModel; }; });