Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show Modal in Durandal with BreezeJS

I'm struggling with this problem for a long time and thought why not ask it here on Stackoverflow! My question is as follows:

I'm creating a Single-Page-Application (SPA) with Durandal and BreezeJS. Whenever a user creates something new the createEntity function from the Breeze Lib is called and I get returned my object. I push this into a Ko.observablearray and voila it is working just fine ;)

Till this everything is working fine.

But now comes the tricky part, I use the ko.observablearray to create a table with data-bind. Each row is clickable and when you click one the function SelectedMemo is called and the 'item' is succesfully passed. But here it comes, when this function needs to create the custom modal nothing happens. I get an error /app/views/.html does not exist. I know what happens here, it is trying to route to a non existing page because there are no View and model-view of the created entity.

How do I fix this problem? SO that when I click a row in my table see all the data of my item?

THis is the code so far:

THe VIew-model:

    define(function (require) {
    var router = require('durandal/plugins/router'),
        app = require('durandal/app'),
        system = require('durandal/system'),
        addmemo = require('viewmodels/modals/addMemo'),
        memo = require('viewmodels/modals/memo'), //probably in the models folder but for now its okay
        dataservice = require('services/dataservice'),
        memos = ko.observableArray([]),
        suspendItemSave = false;

    function extendMemo(memoToExtend) {
        if (memoToExtend.isEditing) return; // already extended

        memoToExtend.isEditing = ko.observable(false);
        //Deze functie wordt getriggerd zodra het aanpassen klaar is!

        // listen for changes with Breeze PropertyChanged event
        memoToExtend.entityAspect.propertyChanged.subscribe(function () {
            if (memoToExtend.propertyChangedPending || suspendItemSave) { return; }
            // throttle property changed response
            // allow time for other property changes (if any) to come through
            memoToExtend.propertyChangedPending = true;
            setTimeout(validateAndSaveModifiedItem, 10);

            function validateAndSaveModifiedItem() {
                if (memoToExtend.entityAspect.entityState.isModified()) {
                    if (memoToExtend.entityAspect.validateEntity()) {
                        dataservice.saveChanges();
                    } else { // errors
                        // handleItemErrors(memoToExtend);
                        memoToExtend.isEditing(true); // go back to editing
                    }
                }
                memoToExtend.propertyChangedPending = false;
            }
        });
    }

    function init() {
        dataservice = new dataservice('api/memo');
        dataservice.getAllRows('AllMemos').then(function (data) {
            data.results.forEach(function (item) {
                //Important step otherwise you are not able to create a memo modal!
                extendMemo(item);
                // memos.push(new memo(item));
                memos.push(item);
            });
            system.log("Initialization succesfull!");
        }).fail(function() {
            system.log("Error initialization!");
        });
    }

    init();
    return {
        displayName: 'Estimating page',
        memos: memos,
        activate: function() {
            system.log("Estimating page started!");
        },
        canDeactivate: function() {
            return app.showMessage('Are you sure you want to leave this page and stop estimating?', 'Navigate', ['Yes', 'No']);
        },
        addMemo: function() {
            app.showModal(new addmemo()).then(function (result) {
                //maby first extend? For editing on the go see hot towel
                if (result != undefined) {                
                    var memoN = dataservice.createT({
                        Description: result[0].Description,
                        CreationDate: result[0].CreationDate,
                        Employee: result[0].User,
                        Type: result[0].Type
                    }, 'tblMemo');

                    if (memoN.entityAspect.validateEntity()) {
                        extendMemo(memoN); //deze 
                        //memos.push(new memo(memoN)); //& deze moeten gewrapped worden!!! anders werkt de entityAspect niet
                        memos.push(memoN);
                        dataservice.saveChanges();
                    }

                    /*
                    if (memoN.entityAspect.validateEntity()) {
                        //memos.push(memoN); //this is not the right thing to add this should be a memo Object!
                        extendMemo(memoN);     
                       // extendMemo(newMemo);
                        memos.push(new memo(memoN.Employee(), memoN.Description(), memoN.Type(), memoN.CreationDate()));
                        dataservice.saveChanges();
                    }*/
                }
            }).fail(function(result) {
                //in future show nice error message, hmmm toastr....?
            });
        },
        selectedMemo: function (selectedMemo, element) {
            //need to make a temp object with data before user clicks okay button or what so ever.
            //THis because the input fields are all observables
            if (selectedMemo) {
                selectedMemo.isEditing(true);
            }

            app.showModal(selectedMemo).then(function (result) {
                if (result) {
                    if (selectedMemo) {
                        selectedMemo.isEditing(false);
                        memos.remove(selectedMemo);
                        selectedMemo.entityAspect.setDeleted();
                        dataservice.saveChanges();
                    }
                }
            }).fail(function() {

            });


            //futher use for deleting memo
            /*
            app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (result) {
                if (result == "Yes") {
                    memos.remove(selectedMemo);
                    selectedMemo.entityAspect.setDeleted();
                    dataservice.saveChanges();
                }
            });
            */ 
        }
    };
});

Also I tryied to create a Memo object but when I do that the EntityAspect is lost in my item! But then the modal is working? How to solve this all?

UPDATE 2:

I have rewritten my Memo Model so it holds the entity in a variable. But the PropertyPendingChanged isn't triggered anymore:S

like image 743
Leroy Meijer Avatar asked Apr 02 '13 15:04

Leroy Meijer


1 Answers

SO I finally did it :) I have coded on this for 3 days but I got it working!

Here is what I did with my code, I created the Memo.js which only holds a variable with the entity. On my view I call this variable and his data. When the user edits a value the subscription function is automaticly triggerd and the new value is passed in the database. Hope its useful, took me 3 full days of about 8 hours each XD

Views

memo.html

<div class="messageBox">
    <div class="modal-header">
        <h2>Memo details</h2>
    </div>
    <div class="modal-body">
        Employee: <input type="text" data-bind="value: MemoEntity._latestValue.Employee"/>
        Description: <input type="text" data-bind="value: MemoEntity._latestValue.Description"/>
        Type: <input type="text" data-bind="value: MemoEntity._latestValue.Type"/>
    </div>
    <div class="modal-footer">
        <ul class="btn-group">
            <button class="btn" data-bind="click: closeModal">Ok</button>
            <button class="btn btn-primary" data-bind="click: deleteMemo">Delete</button>
        </ul> 
    </div>
</div>

Memo model-view

(function () {
    var _this = this;
    //self.dataservice = require('services/dataservice');
    define(function (require) {
        var Memo;
        return Memo = (function () {
            function Memo(dataForMemo) {
                this.MemoEntity = ko.observable(dataForMemo);

               // this.Employee = ko.observable(dataForMemo.entityAspect.entity.Employee());
               // this.Description = ko.observable(dataForMemo.entityAspect.entity.Description());
               // this.Type = ko.observable(dataForMemo.entityAspect.entity.Type());
               // this.CreationDate = ko.observable(dataForMemo.entityAspect.entity.CreationDate());
               // this.isEditing = dataForMemo.entityAspect.entity.isEditing;
            }

            Memo.prototype.closeModal = function () {
                return this.modal.close(false);
            };

            Memo.prototype.deleteMemo = function () {
                return this.modal.close(true);
            };
            return Memo;
        })();
    });
}).call(this);

And my page js

model-view

define(function (require) {
    var router = require('durandal/plugins/router'),
        app = require('durandal/app'),
        system = require('durandal/system'),
        addmemo = require('viewmodels/modals/addMemo'),
        memo = require('viewmodels/modals/memo'), //probably in the models folder but for now its okay
        dataservice = require('services/dataservice'),
        memos = ko.observableArray([]),
        suspendItemSave = false;

    function extendMemo(memoToExtend) {
        if (memoToExtend.isEditing) return; // already extended

        memoToExtend.isEditing = ko.observable(false);
        //Deze functie wordt getriggerd zodra het aanpassen klaar is!

        // listen for changes with Breeze PropertyChanged event
        memoToExtend.entityAspect.propertyChanged.subscribe(function () {
            if (memoToExtend.propertyChangedPending || suspendItemSave) { return; }
            // throttle property changed response
            // allow time for other property changes (if any) to come through
            memoToExtend.propertyChangedPending = true;
            setTimeout(validateAndSaveModifiedItem, 10);

            function validateAndSaveModifiedItem() {
                if (memoToExtend.entityAspect.entityState.isModified()) {
                    if (memoToExtend.entityAspect.validateEntity()) {
                        dataservice.saveChanges();
                    } else { // errors
                        // handleItemErrors(memoToExtend);
                        memoToExtend.isEditing(true); // go back to editing
                    }
                }
                memoToExtend.propertyChangedPending = false;
            }
        });
    }

    function init() {
        dataservice = new dataservice('api/memo');
        dataservice.getAllRows('AllMemos').then(function (data) {
            data.results.forEach(function (item) {
                //Important step otherwise you are not able to create a memo modal!
                extendMemo(item);
                var t = new memo(item);
                memos.push(t);
                //memos.push(item);
            });
            system.log("Initialization succesfull!");
        }).fail(function() {
            system.log("Error initialization!");
        });
    }

    init();
    return {
        displayName: 'Estimating page',
        memos: memos,
        activate: function() {
            system.log("Estimating page started!");
        },
        canDeactivate: function() {
            return app.showMessage('Are you sure you want to leave this page and stop estimating?', 'Navigate', ['Yes', 'No']);
        },
        addMemo: function() {
            app.showModal(new addmemo()).then(function (result) {
                //maby first extend? For editing on the go see hot towel
                if (result != undefined) {                
                    var memoN = dataservice.createT({
                        Description: result[0].Description,
                        CreationDate: result[0].CreationDate,
                        Employee: result[0].User,
                        Type: result[0].Type
                    }, 'tblMemo');

                    if (memoN.entityAspect.validateEntity()) {
                        extendMemo(memoN); //deze 
                        memos.push(new memo(memoN)); //& deze moeten gewrapped worden!!! anders werkt de entityAspect niet
                        dataservice.saveChanges();
                    }

                    /*
                    if (memoN.entityAspect.validateEntity()) {
                        //memos.push(memoN); //this is not the right thing to add this should be a memo Object!
                        extendMemo(memoN);     
                       // extendMemo(newMemo);
                        memos.push(new memo(memoN.Employee(), memoN.Description(), memoN.Type(), memoN.CreationDate()));
                        dataservice.saveChanges();
                    }*/
                }
            }).fail(function(result) {
                //in future show nice error message, hmmm toastr....?
            });
        },
        selectedMemo: function (selectedMemo, element) {
            //need to make a temp object with data before user clicks okay button or what so ever.
            //THis because the input fields are all observables
        //    if (selectedMemo) {
                //selectedMemo.MemoEntity._latestValue.entity.isEditing(true);
               // selectedMemo.isEditing(true);
        //    }

            app.showModal(selectedMemo).then(function (result) {
                if (result) {


                    app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (resultMes) {
                        if (resultMes == "Yes") {
                            memos.remove(selectedMemo);
                            selectedMemo.MemoEntity._latestValue.entityAspect.setDeleted();
                            dataservice.saveChanges();
                        }
                    });


                }
            }).fail(function() {

            });


            //futher use for deleting memo
            /*
            app.showMessage('Do you want to delete this memo?', 'Delete memo', ['Yes', 'No']).then(function (result) {
                if (result == "Yes") {
                    memos.remove(selectedMemo);
                    selectedMemo.entityAspect.setDeleted();
                    dataservice.saveChanges();
                }
            });
            */

        }
    };
});

And my view with the memos

<table class="table table-hover table-striped">
                    <thead>
                        <tr>
                            <th>Created</th><th>User</th><th>Memo</th><th>Type</th>
                        </tr>
                    </thead>
                    <tbody data-bind="visible: memos().length > 0, foreach: memos">
                        <tr data-bind="click: $parent.selectedMemo">
                            <td data-bind="text: MemoEntity._latestValue.CreationDate"></td>
                            <td data-bind="text: MemoEntity._latestValue.Employee"></td>
                            <td data-bind="text: MemoEntity._latestValue.Description"></td>
                            <td data-bind="text: MemoEntity._latestValue.Type"></td>
                        </tr>
                    </tbody>
                    <tbody data-bind="visible: memos().length == 0">
                        <tr>
                            <td colspan="4">NO MEMOS ADDED YET</td>
                        </tr>
                    </tbody>
                </table> 

Hope it helps ;)

like image 97
Leroy Meijer Avatar answered Nov 06 '22 22:11

Leroy Meijer