0

使用 DurandalJS,我创建了一个显示特定数据的 web 应用程序。这些数据是通过 BreezeJS 收集的,并从 durandalJS 框架的激活函数中调用。

当我第一次进入页面 A 时,所有数据都已正确加载。然后,当我使用页面 A 上的链接转到页面 B,然后使用链接从页面 B 回到 A 时,我可以看到数据已加载到我的 knockoutJS observablearrays 中,但未显示!

当页面上有多个可观察数组(例如 A1、B2 和 C3)在第一次加载时,当我在 Web 应用程序上冲浪并返回带有可观察数组的特定页面时,它们都已正确加载,而 A1 和 C3 已加载而 B2 未加载!另一个力矩 A1 和 B2 和 C3 未显示。一切都很随意!

当我按 CTRL + F5 时,一切都已正确加载。这和 DurandalJS 的框架有关系吗?有谁知道如何解决这个问题?

到目前为止我尝试了什么:使用延迟使用停用,以便以正确的方式清理属性,以便可以填写激活

到目前为止什么都没有

图书馆的版本:

  • 淘汰赛JS:2.3.0
  • 微风JS:1.4.0
  • 杜兰达尔JS:1.2.0

这些是我包含的图书馆的当前版本。他们最近更新了,希望这能解决问题,但没有。

这是我的单例数据服务:

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;
        }
    };
})();

在像估计这样的页面上,它被称为如下,这是视图模型:

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);
            });
        },   
    };
});

这是它附带的视图:

    <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">&#8250;</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">&#8250;</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">&#8250;</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">&#8250;</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>

格。乐华

4

4 回答 4

0

编辑

好的,我将尽力帮助您,并在此过程中指出一些事情 -

  1. 在 Visual Studio 或您选择的编辑器中打开您的项目并执行“查找”,搜索整个项目,以及在您的 viewModel 或视图中看到“latestValue”的任何地方,或者除 Knockout 库之外的任何地方,您需要删除它。如果您需要来自 KO Observable 或 ObservableArray 的值,请使用 getter 函数 -

    if (memos._latestValue.length == 0)
    

应该

if (memos().length == 0)

我知道我之前已经为你回答过一个问题并推荐了这个,我回去仔细检查了它是否属实,但你真的需要这样做,你通过使用 _latestValue 绕过了 Knockout 的核心功能。

  1. 我检查了一些您创建的 ID 可观察对象,似乎您创建了它们并将它们设置为 -1 但从不使用它们 - 将它们全部删除,如果您需要 currentContainer 或其他可观察对象的 ID,只需调用 currentContainer()。 ID()。

  2. 在定义 observableArray 时,不需要将其设置为空,也不需要在停用时调用 removeAll()。

第一次定义变量 -

memos = ko.observableArray();

将变量设置为无 -

memos = ko.observableArray([]);

因此,当您停用时,只需将其设置为无,而不是使用 removeAll()。

这似乎需要做很多工作,但实际上并非如此,而且我感觉我们可能会发现为什么您的视图模型在此过程中第二次只加载了一半的数据。

看这里!!!

在某些地方,您将 observables 设置为等于 data.results,这很好,但是让我们尝试清理一下它们(我并不是说数组 data.results 的第一项上没有名为 Customer 的函数,但如果没有这将解决问题) -

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 observables 充满了数据,那么您的查询可能按预期工作。

消除 Knockout 作为问题 - 如果您的视图模型填充了数据,这是一个好兆头。如果视图本身存在绑定问题,您可以尝试以下方法 -

  1. 查看控制台 - 是否有任何数据绑定中断?
  2. 您的视图是否处理在声明绑定后可能会加载数据的情况?

这将等到加载可观察的数组,然后再尝试显示数据 -

<ul data-bind="foreach: myArray"><li data-bind="text: name"></li></ul>

这不会——

<h1 data-bind="text: name" />

但是您可以调试它或防止绑定像这样中断 -

<h1 data-bind="text: $data.name" />

消除杜兰达尔作为问题 -

Durandal 的框架相当稳定,很怀疑你发现了一个没有人发现的 bug。您第一次访问该页面时所做的事情可能与您第二次访问该页面时所做的不同。没有代码,我们无法进一步调试它。

关于 Durandal 的一个重要说明 - 如果您的视图模型是单例对象并且您依赖某些数据始终存在,您应该考虑使用构造函数模块。更多信息@http ://durandaljs.com/documentation/Creating-A-Module/

于 2013-08-01T10:59:58.187 回答
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');
                }
            });
        }
    };
});
于 2013-08-01T14:13:21.870 回答
0

我发现 DurandalJS 框架的 file: 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);
                }
            });
        }
    };
});

当我调试时,我看到了绑定的值。然后我看到 somevalues 确实有时是空的。所以当它们被绑定时它们是空的。但是当我输入一个全新的值时,它们不会重新绑定。

我该如何解决这个问题?只有当所有对微风的异步调用都准备好并且 neccassery 属性已填充时,该页面才被绑定?

于 2013-08-05T13:56:41.913 回答
0

是的,我修好了:)

这是我的解释:每个微风函数我都有 jQuery 延迟对象,并且每页也有一个全局对象。在激活函数中,我调用了 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 的控制台,我看到日志都是在绑定之前执行的!这就是问题所在!

于 2013-08-07T08:47:56.103 回答