【问题标题】:Data won't show on page when postback回发时数据不会显示在页面上
【发布时间】:2013-08-02 04:19:01
【问题描述】:

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

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

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

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

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

目前还没有

图书馆的版本:

  • KnockoutJS: 2.3.0
  • BreezeJS:1.4.0
  • DurandalJS: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>

克。乐华

【问题讨论】:

    标签: knockout.js breeze durandal


    【解决方案1】:

    视图模型:

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

    【讨论】:

    • 当我在 Chrome 或 IE 等浏览器中检查我的控制台时,我看到值在那里:S
    【解决方案2】:

    编辑

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

    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,这很好,但让我们尝试清理一下它们(我并不是说数组中的第一项上没有名为 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 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 的框架相当稳定,很怀疑你发现了一个没有其他人发现的错误。您第一次访问该页面时所做的事情可能与您第二次访问该页面时所做的不同。如果没有代码,我们将无法进一步调试它。

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

    【讨论】:

    • 我已经添加了一些代码一个完整的页面与视图模型和视图希望它有所帮助。我还添加了一些文本和解释。
    • 好吧我在回答中补充了很多,希望能帮助你找到问题。
    • 我已经听从了你的所有建议,但没有一个人完成了这项工作:(还有其他想法吗?
    • 未加载哪个可观察或可观察数组?将有助于诊断
    • 这是非常随机的,在调试中我看到正在加载的视图模型中的值,我通过 Fiddler2 看到它们被正确获取。一次是estimatepropertys,另一次是没有加载的备忘录。有时在正确加载时没有显示:S
    【解决方案3】:

    我发现 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 属性已填充时,该页面才被绑定?

    【讨论】:

      【解决方案4】:

      是的,我修好了:)

      这是我的解释:每个微风函数我都有 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 的控制台,我看到日志都是在绑定之前执行的!这就是问题所在!

      【讨论】:

        猜你喜欢
        • 2017-03-13
        • 1970-01-01
        • 2015-10-05
        • 1970-01-01
        • 2019-07-13
        • 1970-01-01
        • 1970-01-01
        • 2014-08-04
        • 2016-04-13
        相关资源
        最近更新 更多