使用DurandalJS,我创建了一个显示特定数据的Web应用程序。这些数据通过BreezeJS收集,并从durandalJS框架的激活函数中调用。
当我第一次进入页面A时,所有数据都正确加载。然后,当我转到页面B时,页面A上有一个链接,然后从页面B返回到带有链接的A,我可以看到数据已加载到我的knockoutJS observablearrays中,但它没有显示!
当第一次加载时,页面上有多个observablearrays,例如A1,B2和C3,当我在web应用程序上浏览并使用observablearrays返回特定页面时,会加载A1和C3和B2不!另一个时刻A1和B2和C3未显示。它非常随意!
当我按下CTRL + F5时,所有内容都正确加载。这与DurandalJS的框架有什么关系吗?有谁知道如何解决这个问题?
到目前为止我尝试了什么: 使用defferred 使用停用以便以正确的方式清理属性,以便可以填充激活
到目前为止没有什么
图书馆的版本:
这些是我所包含的库的当前版本。他们最近更新了,这可以解决问题,但事实并非如此。
这是我的数据服务,它是一个Singleton:
var DataserviceClass = (function () {
function DataserviceClass() {
this._isSaving = false;
this.suspendItemSave = false;
this.ds = new breeze.DataService({
serviceName: "api/data",
hasServerMetadata: true
});
this.manager = new breeze.EntityManager({dataService: this.ds});
this.metadataStore = this.manager.metadataStore;
this.entityQuery = new breeze.EntityQuery();
this.getMetadataStore = function () {
return this.metadataStore;
};
this.getExportData = function() {
return this.manager.exportEntities();
};
this.getAllRows = function (functionName, expand) {
if (expand == null || expand == undefined) {
this.entityQuery = breeze.EntityQuery.from(functionName);
} else {
this.entityQuery = breeze.EntityQuery.from(functionName).
expand(expand);
}
return this.manager.executeQuery(this.entityQuery);
};
this.getSpecificID = function (functionName, idName, id) {
this.entityQuery = breeze.EntityQuery.from(functionName).where(idName, "==", id);
return this.manager.executeQuery(this.entityQuery);
};
this.createT = function (initialValues, entity) {
return this.manager.createEntity(entity, initialValues);
};
this.saveChanges = function (suppressLogIfNothingToSave) {
if (this.manager.hasChanges()) {
if (this._isSaving) {
setTimeout(this.saveChanges, 50);
return;
}
return this.manager.saveChanges().then(this.saveSucceeded).fail(this.saveFailed).fin(this.saveFinished);
} else if (!suppressLogIfNothingToSave) {
}
};
this.saveSucceeded = function (saveResult) {
this._isSaving = false;
};
this.saveFailed = function (error) {
};
this.saveFinished = function () {
this._isSaving = false;
};
}
var instance;
return {
getInstance: function() {
if (instance == null) {
instance = new DataserviceClass();
instance.constructor = null;
}
return instance;
}
};
})();
在像估计的页面上,它被调用如下,这是viewmodel:
define(function (require) {
var router = require('durandal/plugins/router'),
app = require('durandal/app'),
system = require('durandal/system'),
addmemo = require('viewmodels/modals/addMemo'),
container = require('viewmodels/modals/container'),
memo = require('viewmodels/modals/memo'),
dataservice = require('services/dataservice'),
logger = require('services/logger'),
addRepairOrderLine = require('viewmodels/modals/addRepairOrderLine'),
repairorderline = require('viewmodels/modals/RepairOrderLine'),
customerModal = require('viewmodels/modals/customer'),
currentLoggedInEmployee = ko.observable(),
memos = ko.observableArray([]),
deferred = $.Deferred(),
repairorderlines = ko.observableArray([]),
tasksToMonitor = [],
isLoading = ko.observable(false),
suspendItemSave = false,
rightParameters = true,
notDone = true,
hourscost = ko.observable(0.0),
materialcost = ko.observable(0.0),
grandtotal = ko.observable(0.0),
currentRepairOrderID = -1,
currentOrderID = -1,
currentOrder = ko.observable(),
currentRepairOrder = ko.observable(null),
currentContainerID = -1,
currentCustomer = ko.observable(null),
currentBillingCustomer = ko.observable(null),
currentContainer = ko.observable(null),
showElementFade = function(elem) { if (elem.nodeType === 1) $(elem).hide().slideDown(); },
hideElementFade = function(elem) { if (elem.nodeType === 1) $(elem).slideUp(function() { $(elem).remove(); }); };
//This function is called ones, only when the page hasn't loaded yet!
function init() {
dataservice = DataserviceClass.getInstance();
dataservice.getSpecificID('Employees', 'EmployeeID', 1).then(function (data) {
currentLoggedInEmployee = data.results[0];
}).fail(function(data) {
logger.logError('Error fetching the current logged in employee!', null, null, true);
});
}
init();
return {
displayName: 'Estimating page',
router: router,
currentCustomer: currentCustomer,
currentContainer: currentContainer,
currentRepairOrder: currentRepairOrder,
currentBillingCustomer: currentBillingCustomer,
memos: memos,
repairorderlines: repairorderlines,
isLoading: isLoading,
hourscost: hourscost,
materialcost: materialcost,
grandtotal: grandtotal,
activate: function (Context) {
currentRepairOrder(null);
currentBillingCustomer(null);
rightParameters = true;
//also need to check if ids exist in DB!!
if (!Context.hasOwnProperty("orderid") || isNaN(Context.orderid) ||
!Context.hasOwnProperty("repairorderid") || isNaN(Context.repairorderid)) {
rightParameters = false;
system.log('Not all the right parameters!');
router.navigateTo('#/error'); //eventueel parameters meegeven!
return;
}
//set id's
currentRepairOrderID = Context.repairorderid;
currentOrderID = Context.orderid;
tasksToMonitor = []; //empty the task function
breeze.EntityQuery.from("Orders")
.where("OrderID", "==", parseInt(Context.orderid))
.expand("Customer, Customer.PostCountry, Customer.VisitCountry, Container, Container.ContainerManufacturer, Container.ContainerType, Container.Owner")
.using(dataservice.manager)
.execute().then(function (data) {
if (data.results.length < 1) {
system.log('Not all the right parameters!');
rightParameters = false;
router.navigateTo('#/error'); //eventueel parameters meegeven!
return;
}
//extendItem(data.results[0]);
currentOrder(data.results[0]);
var customer = data.results[0].Customer();
//extendItem(customer);
currentCustomer(customer);
var container = data.results[0].Container();
//extendItem(container);
currentContainer(container);
}).fail(function (data) {
logger.logError('Error fetching the current Order!', null, null, true);
}).fin(function() {
});
//In the future this will be calling the order 2
breeze.EntityQuery.from("RepairOrders")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
.expand("BillingCustomer, BillingCustomer.PostCountry, BillingCustomer.VisitCountry")
.using(dataservice.manager)
.execute().then(function (data) {
currentRepairOrder(data.results[0]);
currentBillingCustomer(data.results[0].BillingCustomer());
}).fail(function (data) {
logger.logError('Error fetching current repairorder!', null, null, true);
}).fin(function() {
//first set the value to true (loading done)
//Call the global function to check each process
tasksToMonitor[0][1] = true;
checkTasks();
});
//by adding this if statements the data is only loaded if it hasn't been loaded yet!
//voor nu alle memos van alle medewerkers, later alleen die van betreffende?
if (memos._latestValue.length == 0) {
breeze.EntityQuery.from("Memos")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
//.expand("Customer, Container, Container.ContainerManufacturer, Container.ContainerType")
.expand("Employee")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
extendItem(item);
memos.push(new memo(item));
});
system.log("Initialization succesfull!");
logger.logSuccess('Initialization succesfull', null, 'estimatepage', true);
}).fail(function (data) {
logger.logError('Error fetching memos!', null, null, true);
}).fin(function() {
tasksToMonitor[1][1] = true;
checkTasks();
});
}
if (repairorderlines._latestValue.length == 0) {
breeze.EntityQuery.from("RepairOrderLines")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
.expand("Customer")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
extendItem(item);
repairorderlines.push(new repairorderline(item));
});
updateFinance();
//
}).fail(function (data) {
logger.logError('Error fetching repairorderlines!', null, null, true);
}).fin(function() {
tasksToMonitor[2][1] = true;
checkTasks();
// deferred.resolve();
});
}
logger.log("Estimating page started!", null, "estimagepage", true);
return deferred.promise();
//return;
},
canDeactivate: function () {
if (rightParameters && notDone) {
return app.showMessage('Are you sure you want to leave this page and stop estimating?', 'Navigate', ['Yes', 'No']);
} else {
return true;
}
},
deactivate: function() {
//remove everything here! I mean remove the data in the models! Everything is already saved ;)
memos.removeAll();
repairorderlines.removeAll();
currentRepairOrderID = -1;
currentOrderID = -1;
currentOrder(null);
currentRepairOrder(null);
currentContainerID = -1;
currentCustomer(null);
currentBillingCustomer(null);
currentContainer(null);
},
showCustomerModal: function(selectedCustomer,element) {
app.showModal(new customerModal(selectedCustomer)).then(function () {
}).fail(function() {
});
},
showContainerModal: function() {
app.showModal(new container(currentContainer, currentOrder())).then(function (result) {
}).fail(function(result) {
});
},
cancelEstimation: function() {
app.showMessage('Do you want to delete this estimation?', 'Delete estimate', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
}
//else if no the user just clicked OK and everything is saved
});
},
selectedRepairOrderLine: function (selectedRepairOrderLine, element) {
app.showModal(selectedRepairOrderLine).then(function (result) {
if (result) {
app.showMessage('Do you want to delete this RepairOrderLine?', 'Delete RepairOrderLine', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
repairorderlines.remove(selectedRepairOrderLine);
selectedRepairOrderLine.RepairOrderLineEntity._latestValue.entityAspect.setDeleted();
dataservice.saveChanges();
updateFinance(); //dont remove this one its called !
logger.logSuccess('Repairline deleted successfully', null, null, true);
}
//else if, no the user just clicked OK and everything is saved so also updatefinance is called a couple of line further
});
}
updateFinance(); //But we must update the finance because things could have been changed!
}).fail(function () {
logger.logError('Something went wrong selecting the memo!', null, 'estimatepage', true);
});
},
selectedMemo: function (selectedMemo, element) {
app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
memos.remove(selectedMemo);
selectedMemo.MemoEntity._latestValue.entityAspect.setDeleted();
dataservice.saveChanges();
}
//else if no the user just clicked OK and everything is saved
}).fail(function () {
logger.logError('Something went wrong selecting the memo!', null, 'estimatepage', true);
});
},
};
});
这是随附的VIew:
<div class="row-fluid">
<div class="span6">
<!-- Estimate Information -->
<!-- Estimate HEADER -->
<div class="fiftypx" data-bind='with: currentContainer'>
<span class="main_title">ESTIMATE</span>
<span class="main_container_number" data-bind="text: ContainerNumber"></span>
</div>
<!-- Estimate Propertys -->
<div class="row-fluid">
<div class="span6">
<fieldset>
<div class="estimate_info" data-bind="with: currentContainer">
<span class="estimatepage_info_text">container number</span>
<div data-bind="" class="estimate_info_DIV">
<span data-bind="text: ContainerNumber"></span>
</div>
</div>
<div style="clear: both;"></div>
<div class="estimate_info" data-bind="with: currentBillingCustomer">
<span class="estimatepage_info_text">billing customer</span>
<div data-bind="click: $parent.showCustomerModal" class="estimate_info_DIV">
<span data-bind="text: Name"></span>
</div>
<button class="flatButtonSmall" data-bind="click: $parent.showCustomerModal">›</button>
</div>
<div style="clear: both;"></div>
<div class="estimate_info" data-bind='with: currentContainer'>
<span class="estimatepage_info_text">equipment</span>
<div data-bind="click: $parent.showContainerModal" class="estimate_info_DIV">
<span data-bind="text: ContainerNumber"></span>
</div>
<button class="flatButtonSmall" data-bind="click: $parent.showContainerModal">›</button>
</div>
<div style="clear: both;"></div>
</fieldset>
</div>
<div class="span6">
<fieldset>
<!--<legend></legend> Deze niet toevoegen uitlijning is dan niet goed!-->
<div class="estimate_info" data-bind="with: currentRepairOrder">
<span class="estimatepage_info_text">repair order</span>
<div class="estimate_info_DIV">
<span data-bind="text: RepairOrderID"></span>
</div>
</div>
<div style="clear: both;"></div>
<div class="estimate_info" data-bind='with: currentCustomer'>
<span class="estimatepage_info_text">relation</span>
<div data-bind="click: $parent.showCustomerModal" class="estimate_info_DIV">
<span data-bind="text: Name"></span>
</div>
<button class="flatButtonSmall" data-bind="click: $parent.showCustomerModal">›</button>
</div>
<div style="clear: both;"></div>
<div class="estimate_info" data-bind="with: currentRepairOrder">
<span class="estimatepage_info_text">creation date</span>
<div class="estimate_info_DIV">
<span data-bind="text: Created().getDate() + '-' + (Created().getMonth() + 1) + '-' + Created().getFullYear()"></span>
</div>
</div>
<div style="clear: both;"></div>
</fieldset>
</div>
</div>
</div>
<div class="span6">
<!-- Memo's -->
<div class="fiftypx">
<span class="main_title">MEMO'S</span>
<button class="newButton" data-bind="click: addMemo">NEW</button>
<button data-bind="click: doneEstimating" style="width: 130px;float: right;margin-right: 25px;" class="flatButtonBig" data-bind="">DONE</button>
<div style="clear: both;"></div>
<div>
<div class="loader" data-bind="css: { active: isLoading }">
<i class="icon-spinner icon-2x icon-spin"></i>
</div>
</div>
</div>
<div id="memosTable">
<table class="table" style="margin-left: -25px;">
<thead>
<tr>
<th></th><th>date / user</th><th>memo</th><th></th>
</tr>
</thead>
<tbody data-bind="visible: memos().length > 0, foreach: memos">
<tr class="rowStyleFront">
<td style="width:25px;"></td>
<td style="width: 115px;">
<!-- date and user -->
<!-- text: MemoEntity._latestValue.CreationDate -->
<span class="upperSpan" data-bind="">Datum</span>
<div style="clear: both;"></div>
<span class="lowerSpan" data-bind="text: MemoEntity._latestValue.Employee().Username()"></span>
</td>
<td style="width: 300px;">
<!-- memo -->
<span style="display: inline; background-color: #f4931D; color: #FFFFFF; padding-right: 7px; padding-left: 5px;" class="upperSpan" data-bind="textToUpperCase: MemoEntity._latestValue.Type"></span>
<div style="clear: both;"></div>
<span style="margin-top: 20px; width: inherit;" class="lowerSpan" data-bind="text: MemoEntity._latestValue.Description"></span>
</td>
<td style="width: 50px;"><button data-bind="click: $parent.selectedMemo" style="float: right;" class="flatButtonBig" data-bind="">X</button></td>
</tr>
</tbody>
<tbody data-bind="visible: memos().length == 0">
<tr class="rowStyleFront">
<td style="width:25px;"></td>
<td colspan="3">You haven't made any memo's yet.</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span6">
<!-- Add new repairline button and text -->
<div class="fiftypx">
<span class="main_title">REPAIRLINES</span>
<button class="newButton" data-bind="click: addRepairline">NEW</button>
</div>
</div>
<div class="span6" style="line-height: 50px;">
<!-- totals! -->
<div class="row-fluid">
<div class="span4">Hours cost: <span style="font-size: 16px;" data-bind="text: hourscost()"></span></div>
<div class="span4">Materials: <span style="font-size: 16px;" data-bind="text: materialcost()"></span></div>
<div class="span4">Total: <span style="font-size: 16px;" data-bind="text: grandtotal()"></span></div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<!-- Table with all repairlines -->
<table class="table" style="margin-left: -25px;">
<thead>
<tr>
<th></th>
<th>Description</th>
<th></th>
<th>Code</th>
<th>Mat</th>
<th>LOC</th>
<th>Rep</th>
<th>DAM</th>
<th>Customer</th>
<th>IsAgreement</th>
<th>Qty</th>
<th>Hours</th>
<th>Tariff</th>
<th>Costs</th>
<th>Lessee</th>
<th>Authorized</th>
<th>DoRepair</th>
<th><!-- Button --></th> <!-- 17 rijen -->
</tr>
</thead>
<tbody data-bind="visible: repairorderlines().length > 0, foreach: repairorderlines">
<tr class="rowStyleFront">
<td style="width:25px;"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.Description"></td>
<td></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.InternalCode"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.MaterialCode"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.LocationCode"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.RepairCode"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.DamageCode"></td>
<td style="text-align: left;" data-bind="click: $parent.selectedRepairOrderLine, text: RepairOrderLineEntity._latestValue.Customer().Name()"></td>
<td><input type="checkbox" data-bind="checked: RepairOrderLineEntity._latestValue.IsAgreement"/></td>
<td data-bind="click: $parent.selectedRepairOrderLine, numericText: RepairOrderLineEntity._latestValue.Quantity"></td>
<td data-bind="click: $parent.selectedRepairOrderLine, numericText: RepairOrderLineEntity._latestValue.Hours"></td>
<td data-bind="click: $parent.selectedRepairOrderLine, numericText: RepairOrderLineEntity._latestValue.Tariff"></td>
<td data-bind="click: $parent.selectedRepairOrderLine, numericText: RepairOrderLineEntity._latestValue.Costs"></td>
<td data-bind="click: $parent.selectedRepairOrderLine">-</td>
<td><input type="checkbox" data-bind="checked: RepairOrderLineEntity._latestValue.IsAuthorized"/></td>
<td><input type="checkbox" data-bind="checked: RepairOrderLineEntity._latestValue.DoRepair"/></td>
<td style="width: 50px;"><button class="flatButtonBig" data-bind="click: $parent.selectedRepairOrderLine">›</button></td>
</tr>
</tbody>
<tbody data-bind="visible: repairorderlines().length == 0">
<tr class="rowStyleFront">
<td style="width:25px;"></td>
<td colspan="16">You haven't made any repairlines yet.</td>
</tr>
</tbody>
</table>
</div>
</div>
的Gr。乐华
答案 0 :(得分:0)
修改强>
好的,我会尽力帮助你,并指出一些事情 -
在Visual Studio或您选择的编辑器中打开您的项目并执行“查找”,搜索整个项目,以及您看到的任何地方&#39; latestValue&#39;在您的viewModel或视图中使用,或者除了Knockout Library内部以外的任何地方,您需要删除它。如果需要来自KO Observable或ObservableArray的值,请使用getter函数 -
if (memos._latestValue.length == 0)
应该是
if (memos().length == 0)
我知道我之前已经为您回答了一个问题并推荐了这个问题,我回过头来仔细检查它是否属实,但是认真地说你需要做到这一点,你通过使用绕过了Knockout的核心功能_latestValue。
我检查了你创建的一些ID observable,看起来你创建了它们并将它们设置为-1但从不使用它们 - 将它们全部删除,如果你需要currentContainer或其他可观察的ID只需调用currentContainer()。id()。
当您定义observableArray时,您不需要将其设置为空,也不需要在停用时调用removeAll()。
第一次定义变量 -
memos = ko.observableArray();
将变量设置为无 -
memos = ko.observableArray([]);
因此,当您停用时,只需将其设置为空,而不是使用removeAll()。
这似乎很多工作,但它确实没有,我觉得我们可能会发现为什么你的视图模型在这个过程中第二次只加载了一半的数据。
看这里!!!
在一些地方你设置的observables等于data.results,这很好,但让我们尝试清理一下(我不是说没有名为Customer的功能)数组data.results中的第一项,但如果没有,这将解决问题) -
currentOrder(data.results[0]);
var customer = data.results[0].Customer();
//extendItem(customer);
currentCustomer(customer);
var container = data.results[0].Container();
//extendItem(container);
currentContainer(container);
让我们将其调整为 -
currentOrder(data.results[0]);
currentCustomer(currentOrder().Customer());
currentContainer(currentOrder().Container());
* 您的停用功能*
deactivate: function() {
memos([]);
repairorderlines([]);
currentOrder(null);
currentRepairOrder(null);
currentCustomer(null);
currentBillingCustomer(null);
currentContainer(null);
},
原始答案
消除Breeze问题 - 如果你的Knockout observable充满了数据,那么你的查询可能正在按预期工作。
消除Knockout问题 - 如果您的视图模型填充了数据,这是一个好兆头。如果视图本身存在绑定问题,您可以尝试一些事项 -
在尝试显示数据之前,这将等到加载一个可观察数组 -
<ul data-bind="foreach: myArray"><li data-bind="text: name"></li></ul>
这不会 -
<h1 data-bind="text: name" />
但你可以调试它或防止绑定像这样破坏 -
<h1 data-bind="text: $data.name" />
消除Durandal问题 -
Durandal的框架相当稳定,你发现了一个其他人没有发现的错误,这是非常值得怀疑的。您第一次访问该页面的可能性与第二次访问该页面的方式不同。没有代码,我们可以帮助进一步调试它。
关于Durandal的一个关键注意事项 - 如果您的视图模型是Singleton对象并且您依赖于某些数据总是,那么您应该考虑使用构造函数模块。更多信息@ http://durandaljs.com/documentation/Creating-A-Module/
答案 1 :(得分:0)
视图模型:
define(function (require) {
var router = require('durandal/plugins/router'),
app = require('durandal/app'),
system = require('durandal/system'),
addmemo = require('viewmodels/modals/addMemo'),
container = require('viewmodels/modals/container'),
memo = require('viewmodels/modals/memo'), //probably in the models folder but for now its okay
dataservice = require('services/dataservice'),
logger = require('services/logger'),
addRepairOrderLine = require('viewmodels/modals/addRepairOrderLine'),
repairorderline = require('viewmodels/modals/RepairOrderLine'),
customerModal = require('viewmodels/modals/customer'),
currentLoggedInEmployee = ko.observable(),
memos = ko.observableArray(),
deferred = $.Deferred(),
repairorderlines = ko.observableArray(),
tasksToMonitor = [],
isLoading = ko.observable(false),
suspendItemSave = false,
rightParameters = true,
notDone = true,
hourscost = ko.observable(0.0),
materialcost = ko.observable(0.0),
grandtotal = ko.observable(0.0),
currentRepairOrderID = -1,
currentOrderID = -1,
currentOrder = ko.observable(),
currentRepairOrder = ko.observable(null),
currentContainerID = -1,
currentCustomer = ko.observable(null),
currentBillingCustomer = ko.observable(null),
currentContainer = ko.observable(null),
showElementFade = function(elem) { if (elem.nodeType === 1) $(elem).hide().slideDown(); },
hideElementFade = function(elem) { if (elem.nodeType === 1) $(elem).slideUp(function() { $(elem).remove(); }); };
function extendItem(itemToExtend) {
if (itemToExtend.isEditing) return; // already extended
itemToExtend.isEditing = ko.observable(false);
//Deze functie wordt getriggerd zodra het aanpassen klaar is!
// listen for changes with Breeze PropertyChanged event
itemToExtend.entityAspect.propertyChanged.subscribe(function () {
if (itemToExtend.propertyChangedPending || suspendItemSave) { return; }
// throttle property changed response
// allow time for other property changes (if any) to come through
itemToExtend.propertyChangedPending = true;
setTimeout(validateAndSaveModifiedItem, 10);
function validateAndSaveModifiedItem() {
if (itemToExtend.entityAspect.entityState.isModified()) {
if (itemToExtend.entityAspect.validateEntity()) {
dataservice.saveChanges();
} else { // errors
itemToExtend.isEditing(true); // go back to editing
}
//also update finance!
updateFinance();
}
itemToExtend.propertyChangedPending = false;
}
});
}
function updateFinance() {
materialcost(0.0);
hourscost(0.0);
grandtotal(0.0);
ko.utils.arrayForEach(repairorderlines(), function (line) {
if (line.RepairOrderLineEntity().DoRepair()) {
var materialcostTemp = (line.RepairOrderLineEntity().Costs() * line.RepairOrderLineEntity().Quantity()) + materialcost();
materialcost(materialcostTemp);
var hourscostTemp = (line.RepairOrderLineEntity().Tariff() * line.RepairOrderLineEntity().Hours()) + hourscost();
hourscost(hourscostTemp);
}
});
// materialcost = ko.observable(materialcost);
// hourscost = ko.observable(hourscost);
grandtotal(materialcost() + hourscost());
//Showing the rounded numbers with the euro sign
hourscost("€ " + parseFloat(Math.round(hourscost() * 100) / 100).toFixed(2));
materialcost("€ " + parseFloat(Math.round(materialcost() * 100) / 100).toFixed(2));
grandtotal("€ " + parseFloat(Math.round(grandtotal() * 100) / 100).toFixed(2));
}
//This function checks each task in the tasktomonitor array when they are all false (so loading is done)
//The global iSloading is set to false, because loading is done:)
function checkTasks() {
var loadingDone = true;
tasksToMonitor.forEach(function (item) {
if (item[1] == false)
loadingDone = false;
});
if (loadingDone) {
deferred.resolve();
isLoading(false);
}
}
//This function is called ones, only when the page hasn't loaded yet!
function init() {
dataservice = DataserviceClass.getInstance();
dataservice.getSpecificID('Employees', 'EmployeeID', 1).then(function (data) {
currentLoggedInEmployee = data.results[0];
}).fail(function(data) {
logger.logError('Error fetching the current logged in employee!', null, null, true);
});
}
init();
return {
displayName: 'Estimating page',
router: router,
currentCustomer: currentCustomer,
currentContainer: currentContainer,
currentRepairOrder: currentRepairOrder,
currentBillingCustomer: currentBillingCustomer,
memos: memos,
repairorderlines: repairorderlines,
isLoading: isLoading,
hourscost: hourscost,
materialcost: materialcost,
grandtotal: grandtotal,
activate: function (Context) {
currentRepairOrder(null);
currentBillingCustomer(null);
rightParameters = true;
//also need to check if ids exist in DB!!
if (!Context.hasOwnProperty("orderid") || isNaN(Context.orderid) ||
!Context.hasOwnProperty("repairorderid") || isNaN(Context.repairorderid)) {
rightParameters = false;
system.log('Not all the right parameters!');
router.navigateTo('#/error'); //eventueel parameters meegeven!
return;
}
//set id's
currentRepairOrderID = Context.repairorderid;
currentOrderID = Context.orderid;
tasksToMonitor = []; //empty the task function
//fetching all necessary information
//estimatepage/:orderid/:repairorderid
//Fetch:
/*
billing customer
owner container
container number
container propertys
repair order
creation date of repairorder
fetching memo's with repairorder
fetching repairorderlines
*/
//In this order the container fetch right away, thats one call less to the server
breeze.EntityQuery.from("Orders")
.where("OrderID", "==", parseInt(Context.orderid))
.expand("Customer, Customer.PostCountry, Customer.VisitCountry, Container, Container.ContainerManufacturer, Container.ContainerType, Container.Owner")
.using(dataservice.manager)
.execute().then(function (data) {
if (data.results.length < 1) {
system.log('Not all the right parameters!');
rightParameters = false;
router.navigateTo('#/error'); //eventueel parameters meegeven!
return;
}
currentOrder(data.results[0]);
currentCustomer(currentOrder().Customer());
currentContainer(currentOrder().Container());
}).fail(function (data) {
logger.logError('Error fetching the current Order!', null, null, true);
}).fin(function() {
});
//In the future this will be calling the order 2
tasksToMonitor.push(new Array('fetch_repairorders', false));
breeze.EntityQuery.from("RepairOrders")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
.expand("BillingCustomer, BillingCustomer.PostCountry, BillingCustomer.VisitCountry")
.using(dataservice.manager)
.execute().then(function (data) {
currentRepairOrder(data.results[0]);
currentBillingCustomer(data.results[0].BillingCustomer());
}).fail(function (data) {
logger.logError('Error fetching current repairorder!', null, null, true);
}).fin(function() {
//first set the value to true (loading done)
//Call the global function to check each process
tasksToMonitor[0][1] = true;
checkTasks();
});
//by adding this if statements the data is only loaded if it hasn't been loaded yet!
//voor nu alle memos van alle medewerkers, later alleen die van betreffende?
tasksToMonitor.push(new Array('fetch_memos', false));
if (memos().length == 0) {
breeze.EntityQuery.from("Memos")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
//.expand("Customer, Container, Container.ContainerManufacturer, Container.ContainerType")
.expand("Employee")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
extendItem(item);
memos.push(new memo(item));
});
system.log("Initialization succesfull!");
logger.logSuccess('Initialization succesfull', null, 'estimatepage', true);
}).fail(function (data) {
logger.logError('Error fetching memos!', null, null, true);
}).fin(function() {
tasksToMonitor[1][1] = true;
checkTasks();
});
}
tasksToMonitor.push(new Array('fetch_repairorderlines', false));
if (repairorderlines().length == 0) {
breeze.EntityQuery.from("RepairOrderLines")
.where("RepairOrderID", "==", parseInt(Context.repairorderid))
.expand("Customer")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
extendItem(item);
repairorderlines.push(new repairorderline(item));
});
updateFinance();
//
}).fail(function (data) {
logger.logError('Error fetching repairorderlines!', null, null, true);
}).fin(function() {
tasksToMonitor[2][1] = true;
checkTasks();
// deferred.resolve();
});
}
logger.log("Estimating page started!", null, "estimagepage", true);
return deferred.promise();
//return;
},
canDeactivate: function () {
if (rightParameters && notDone) {
return app.showMessage('Are you sure you want to leave this page and stop estimating?', 'Navigate', ['Yes', 'No']);
} else {
return true;
}
},
deactivate: function() {
//remove everything here! I mean remove the data in the models! Everything is already saved ;)
memos.removeAll();
repairorderlines.removeAll();
currentRepairOrderID = -1;
currentOrderID = -1;
currentOrder(null);
currentRepairOrder(null);
currentContainerID = -1;
currentCustomer(null);
currentBillingCustomer(null);
currentContainer(null);
},
showCustomerModal: function(selectedCustomer,element) {
app.showModal(new customerModal(selectedCustomer)).then(function () {
}).fail(function() {
});
},
showContainerModal: function() {
app.showModal(new container(currentContainer, currentOrder())).then(function (result) {
}).fail(function(result) {
});
},
cancelEstimation: function() {
app.showMessage('Do you want to delete this estimation?', 'Delete estimate', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
//memos.remove(selectedMemo);
//selectedMemo.MemoEntity().entityAspect.setDeleted();
// dataservice.saveChanges();
}
//else if no the user just clicked OK and everything is saved
});
},
addRepairline: function() {
//logger.log('Clicked a button yeeeh', null, 'estimatepage', true);
//Dit doen: addreapirline de repairline laten maken en de foto's
//dan de gemaakte repairline teruggeven aan deze functie.
var t = currentRepairOrder().ID();
app.showModal(new addRepairOrderLine(currentRepairOrderID, currentCustomer,currentBillingCustomer)).then(function (result) {
if (result != undefined) {
extendItem(result);
repairorderlines.push(new repairorderline(result));
updateFinance();
}
}).fail(function(result) {
logger.logError('Error fetching result adding repairline', null, null, true);
});
},
addMemo: function() {
app.showModal(new addmemo(currentLoggedInEmployee)).then(function (result) {
if (result != undefined) {
var memoN = dataservice.createT({
Description: result[0].Description,
EmployeeID: result[0].EmployeeID, //Dit moet echt de employee zelf zijn niet zijn ID!!!
Type: result[0].Type,
RepairOrderID: currentRepairOrderID
}, 'tblMemo');
if (memoN.entityAspect.validateEntity()) {
extendItem(memoN);
memos.push(new memo(memoN));
dataservice.saveChanges();
logger.logSuccess('Memo added succesfully!', null, null, true);
}
}
}).fail(function(result) {
logger.logError('Something went wrong adding a memo!', null, 'estimatepage', true);
});
},
selectedRepairOrderLine: function (selectedRepairOrderLine, element) {
app.showModal(selectedRepairOrderLine).then(function (result) {
if (result) {
app.showMessage('Do you want to delete this RepairOrderLine?', 'Delete RepairOrderLine', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
repairorderlines.remove(selectedRepairOrderLine);
selectedRepairOrderLine.RepairOrderLineEntity().entityAspect.setDeleted();
dataservice.saveChanges();
updateFinance(); //dont remove this one its called !
logger.logSuccess('Repairline deleted successfully', null, null, true);
}
//else if, no the user just clicked OK and everything is saved so also updatefinance is called a couple of line further
});
}
updateFinance(); //But we must update the finance because things could have been changed!
}).fail(function () {
logger.logError('Something went wrong selecting the memo!', null, 'estimatepage', true);
});
},
selectedMemo: function (selectedMemo, element) {
app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
memos.remove(selectedMemo);
selectedMemo.MemoEntity().entityAspect.setDeleted();
dataservice.saveChanges();
}
//else if no the user just clicked OK and everything is saved
}).fail(function () {
logger.logError('Something went wrong selecting the memo!', null, 'estimatepage', true);
});
},
/*
selectedMemo: function (selectedMemo, element) {
app.showModal(selectedMemo).then(function (result) {
if (result) {
app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
memos.remove(selectedMemo);
selectedMemo.MemoEntity().entityAspect.setDeleted();
dataservice.saveChanges();
}
//else if no the user just clicked OK and everything is saved
});
}
}).fail(function() {
logger.logError('Something went wrong selecting the memo!', null, 'estimatepage', true);
});
},
*/
/*
getUser: function (userId) {
var t;
dataservice.getSpecificID('AllEmployees', 'EmployeeID', userId).then(function (data) {
t = "Dit is mijn tekst: " + data.results[0].Username();
return t;
});
return t;
},*/
removeMemos: function () {
var memoSelectedToBeRemoved = false;
$.each(memos(), function (i, l) {
if (l.markedForDeletion()) {
memoSelectedToBeRemoved = true;
}
});
if (memoSelectedToBeRemoved == false) {
app.showMessage('No memos selected!','No memos');
return; //No memos selected to be deleted!
}
app.showMessage('Do you want to delete the selected memos?', 'Delete memos', ['Yes', 'No']).then(function(resultMessageBox) {
if (resultMessageBox == "Yes") {
//create a temp new KOarray
//for each memo that is not to be deleted put them in a new list
//At the end remove all memos from memos. then push all memos from the temp list to memos.
var newMemoList = ko.observableArray([]);
var numberOfMemos = memos().length;
$.each(memos(), function (i, l) {
if (!l.markedForDeletion()) {
newMemoList.push(l);
} else {
l.MemoEntity().entityAspect.setDeleted();
}
});
dataservice.saveChanges();
memos.removeAll();
$.each(newMemoList(), function (i, l) {
memos.push(l);
});
logger.logSuccess('A total of: ' + (numberOfMemos - newMemoList().length) + ' memos have been removed.', null, null, true);
}
});
},
doneEstimating: function () {
if (repairorderlines().length < 1) {
app.showMessage('No repairlines added yet!', 'Estimate cannot be ready');
return;
}
app.showMessage('Are you sure you are done estimating?', 'Estimate done', ['Yes', 'No']).then(function (resultMessageBox) {
if (resultMessageBox == "Yes") {
//sent repairOrderID to server
//server fetch all data like repairorderlines etc.
//server sents mail to user
notDone = false;
router.navigateTo('startingpage');
}
});
}
};
});
答案 2 :(得分:0)
我发现DurandalJS框架的文件:viewModelBinder.js负责绑定。
define(['./system'], function (system) {
var viewModelBinder;
var insufficientInfoMessage = 'Insufficient Information to Bind';
var unexpectedViewMessage = 'Unexpected View Type';
function doBind(obj, view, action) {
if (!view || !obj) {
if (viewModelBinder.throwOnErrors) {
throw new Error(insufficientInfoMessage);
} else {
system.log(insufficientInfoMessage, view, obj);
}
return;
}
if (!view.getAttribute) {
if (viewModelBinder.throwOnErrors) {
throw new Error(unexpectedViewMessage);
} else {
system.log(unexpectedViewMessage, view, obj);
}
return;
}
var viewName = view.getAttribute('data-view');
try {
system.log('Binding', viewName, obj);
viewModelBinder.beforeBind(obj, view);
action();
viewModelBinder.afterBind(obj, view);
} catch (e) {
if (viewModelBinder.throwOnErrors) {
throw new Error(e.message + ';\nView: ' + viewName + ";\nModuleId: " + system.getModuleId(obj));
} else {
system.log(e.message, viewName, obj);
}
}
}
return viewModelBinder = {
beforeBind: system.noop,
afterBind:system.noop,
bindContext: function(bindingContext, view, obj) {
if (obj) {
bindingContext = bindingContext.createChildContext(obj);
}
doBind(bindingContext, view, function () {
if (obj && obj.beforeBind) {
obj.beforeBind(view);
}
ko.applyBindings(bindingContext, view);
if (obj && obj.afterBind) {
obj.afterBind(view);
}
});
},
bind: function(obj, view) {
doBind(obj, view, function () {
if (obj.beforeBind) {
obj.beforeBind(view);
}
ko.applyBindings(obj, view);
console.log(obj);
if (obj.afterBind) {
obj.afterBind(view);
}
});
}
};
});
当我调试时,我会看到绑定的值。然后我看到有些值确实有时是空的。因此,当它们绑定时它们是空的。但是当我输入一个全新的值时,它们不会重新绑定。
我该如何解决这个问题?当所有对微风的异步调用都准备好并且neccassery属性被填充时,该页面才被绑定?
答案 3 :(得分:0)
是的,我修好了它:)
这里是我的解释:每个微风函数我都有jQuery延迟对象,每页还有一个全局。在activate函数中,我调用jQuery的when函数,其中所有函数都被执行。
define(function (require) {
var app = require('durandal/app'),
suspendItemSave = false,
system = require('durandal/system'),
router = require('durandal/plugins/router'),
dataservice = require('services/dataservice'),
logger = require('services/logger'),
allCustomers = ko.observableArray(),
allCountries = ko.observableArray(),
allVats = ko.observableArray(),
allCurrencys = ko.observableArray(),
allContainerPropertySettings = ko.observableArray(),
entireRepairlineLib = ko.observableArray(),
repairAgreementsLib = ko.observableArray(),
addVatModal = require('viewmodels/manager/addVat'),
vatModal = require('viewmodels/manager/Vat'),
addCurrencyModal = require('viewmodels/manager/addCurrency'),
currencyModal = require('viewmodels/manager/currency'),
addCountryModal = require('viewmodels/manager/addCountry'),
countryModal = require('viewmodels/manager/country'),
addContainerPropertySettingModal = require('viewmodels/manager/addContainerPropertySetting'),
containerPropertySettingModal = require('viewmodels/manager/containerPropertySetting'),
repairlineModal = require('viewmodels/manager/predefinedRepairline'),
addPredefinedRepairlineModal = require('viewmodels/manager/addPredefinedRepairline'),
repairAgreement = require('viewmodels/manager/repairAgreement'),
deferred = $.Deferred();
function getEntireRepairLib() {
var d = $.Deferred();
breeze.EntityQuery.from("EntireRepairLineLib")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
extendItem(item);
entireRepairlineLib.push(new repairlineModal(item));
});
system.log("Succesfully fetched EntireRepairLineLib");
d.resolve();
}).fail(function (data) {
});
return d.promise();
}
function getRepairAgreements() {
var d = $.Deferred();
breeze.EntityQuery.from("RepairAgreements")
.using(dataservice.manager)
.execute().then(function(data) {
data.results.forEach(function(item) {
extendItem(item);
repairAgreementsLib.push(new repairAgreement(item));
});
system.log("Succesfully fetched RepairAgreement");
d.resolve();
});
return d.promise();
}
function init() {
dataservice = DataserviceClass.getInstance(); //Get the dataservice instance.
}
init();
return {
router: router,
displayName: 'Management page',
allCustomers: allCustomers,
allCountries: allCountries,
allVats: allVats,
allCurrencys: allCurrencys,
allContainerPropertySettings: allContainerPropertySettings,
entireRepairlineLib: entireRepairlineLib,
repairAgreementsLib: repairAgreementsLib,
activate: function () {
$.when(getEntireRepairLib(), getRepairAgreements(), etc, etc, .....)
.done(function () {
deferred.resolve();
console.log("Done loading");
logger.log("Managementpage started!", null, null, true);
system.log("Managementpage started!");
});
return deferred.promise();
},
deactivate: function() {
allCustomers([]);
allCountries([]);
allVats([]);
allCurrencys([]);
allContainerPropertySettings([]);
entireRepairlineLib([]);
repairAgreementsLib([]);
deferred = $.Deferred(); //reset the deferred!
}
};
});
如果还有其他(更好的)方法请立即让我!我检查了Chrome的控制台,我看到日志都是在绑定之前执行的!那就是问题!