问题
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?
回答1:
attachments
is a property on an instance of ComposePopupView
.
addDropboxAttachment
is a method on the prototype of ComposePopupView
that has to be called with the this
context referring to an instance
of ComposePopupView
in order to work.
There are several ways to solve the issue. For example:
Most likely: you haven't created an instance yet:
DropBox = __webpack_require__(/*! View/Popup/Compose */ 31); const dropBox = new DropBox(); dropBox.addDropboxAttachment(aFiles[0]);
Likely: You've already created an instance but can't access it: Pass a reference to the instance you want to refer to along in your constructors.
Are you only going to ever create one instance of
ComposePopupView
? Have a look at the "Singleton" pattern. E.g.:// "Private" to the module const MySingletonClass = function() { /* ... */ } MySingletonClass.prototype.someMethod = function () { }; let singletonInstance = null; // Only expose a way to get the instance: export const getSingletonInstance = function() { if (!singletonInstance) singletonInstance = new MySingletonClass(); return singletonInstance; } // In another module: import { getSingletonInstance } from "./MySingletonClass"; const dropBox = getSingletonInstance(); dropBox.someMethod(aFiles[0]);
Planning on creating several instances that share the
attachments
data? Make it a static value.
回答2:
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).
来源:https://stackoverflow.com/questions/51883917/knockoutjs-update-observable-from-another-modelview