knockout.jsobservablemodel-view

KnockoutJS - update observable from another modelview


I have an existing ComposePopupView() modelview which contains observable

this.attachments = ko.observableArray([]);

and a method below

ComposePopupView.prototype.addDropboxAttachment = function (oDropboxFile)
{
    var
        oAttachment = null,
        iAttachmentSizeLimit = Utils.pInt(Settings.settingsGet('AttachmentLimit')),
        mSize = oDropboxFile['bytes']
    ;

    oAttachment = new ComposeAttachmentModel(
        oDropboxFile['link'], oDropboxFile['name'], mSize
    );

    oAttachment.fromMessage = false;
    oAttachment.cancel = this.cancelAttachmentHelper(oDropboxFile['link']);
    oAttachment.waiting(false).uploading(true).complete(false);

    this.attachments.push(oAttachment);

    this.attachmentsPlace(true);

    if (0 < mSize && 0 < iAttachmentSizeLimit && iAttachmentSizeLimit < mSize)
    {
        oAttachment.uploading(false).complete(true);
        oAttachment.error(Translator.i18n('UPLOAD/ERROR_FILE_IS_TOO_BIG'));
        return false;
    }

    Remote.composeUploadExternals(function (sResult, oData) {

        var bResult = false;
        oAttachment.uploading(false).complete(true);

        if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
        {
            if (oData.Result[oAttachment.id])
            {
                bResult = true;
                oAttachment.tempName(oData.Result[oAttachment.id]);
            }
        }

        if (!bResult)
        {
            oAttachment.error(Translator.getUploadErrorDescByCode(Enums.UploadErrorCode.FileNoUploaded));
        }

    }, [oDropboxFile['link']]);

    return true;
};

Then I have created my other modelview called UsersDocumentsPopupView() where I'm accessing above method as

DropBox = __webpack_require__(/*! View/Popup/Compose */ 31)
....
DropBox.prototype.addDropboxAttachment(aFiles[0]);

but it throws an error

Cannot read property 'attachments' of undefined

Then I have decided to add observable

this.attachments = ko.observableArray([]);

to my modelview and then tired to do

this.attachment.push(oAttachment);

where oAttachment is an object taken from aFiles array but still I'm getting the same error.

My question is how or even if can I update observable attachments from one modelview executing another modelview?

PS. When I will do code below in the ComposePopupView() it works fine

var aFiles = [JSON.parse('{"isDir": false,  "name": "koala.jpg", "bytes": 780831,"link": "http://localhost/data/koala.jpg","id": "id:UxmT1S5QcFAAAAAAAAAACw"}')];

if (aFiles && aFiles[0] && aFiles[0]['link'])
{
  console.log("Test");
  self.addDropboxAttachment(aFiles[0]);
}

So in this case how can I pass data aFiles from the UsersDocumentsPopupView() to ComposePopupView() modelview?


Solution

  • I have ended up to using Knockout's pub/sub functionality.

    Basic example below:

    var postbox = ko.observable();
    
    function MyModalViewA()
    {
        var _self = this;
        var test = new Array();
        _self.rows = ko.observableArray([]);
    
        postbox.subscribe(function(newValue) {         
              _self.rows.push(newValue);
              //test = test.concat(newValue);
              console.log("Rows " + JSON.stringify(test));
          }, null, "NewRowAvailable"
          );
    };
    
    function MyModalViewB()
    {
        var _self = this;
    
        _self.search = function() {
    
            var newRow = JSON.parse('{ "label" : "abc" }');
            postbox.notifySubscribers(newRow, "NewRowAvailable");      
        };
    };
    
    var vma = new MyModalViewA();
    ko.applyBindings(vma, $("#vma").get(0));
    
    var vmb = new MyModalViewB();
    ko.applyBindings(vmb, $("#vmb").get(0));
    

    The first view model subscribes to a specific topic and the second view model notifies through the postbox on that topic. There is no direct dependency on each other.

    Certainly the postbox would not need to be global and could be passed into the view model constructor functions or just created inside a self-executing function.

    Sample: http://jsfiddle.net/xpvt214o/708647/

    Also, the postbox could just be a ko.subscribable() (which is included in the ko.observable functions).