grofit / knockout.merge Goto Github PK
View Code? Open in Web Editor NEWAdds basic merging functionality into knockout js mapping namespace
License: MIT License
Adds basic merging functionality into knockout js mapping namespace
License: MIT License
Not 100% sure why yet but I've just discovered that the array merging isn't working properly for simple objects (e.g. an array of numbers).
Essentially given the following, the resultant viewModel.values()[0]
will still equal 0.
var viewModel = { values: ko.observableArray([ 0 ]); }
var data = { values: [50] };
ko.merge.fromJS(viewModel, data);
I'm looking into this at the moment, if I find a resolution I'll submit a pull request.
I'm trying to write a 'complex' merge but it seems to be failing. Essentially my sub-properties are being overwritten with non-observable fields, when they should remain observable. I'm not sure why this is the case. You can see a JSFfiddle to demonstrate this (I found the issue when computed observables that I've taken out for simplicity couldn't read from sibling computed fields) http://jsfiddle.net/IPWright83/fnc0xysk/2/
So I've started by defining some data which I create a view model from using ko.mapping.fromJS
:
var data = {
name: "Sign-off",
id: "XX",
values: [{ text: "Signed-off", count: 150, color: "#5fb5cc" },
{ text: "Submitted", count: 90, color: "#75d181" },
{ text: "Not Submitted", count: 75, color: "#f8a25b" }
],
aggregates: {
count: 650
}
};
var vm = ko.mapping.fromJS(data);
If I log the vm
, then vm.values[0]
and finally vm.values[0].text
I get the following. Ending up with an observable field as I expected:
Once I've done this I wait for a second and attempt to update the data using ko.merge.fromJS
and this is where I start getting the problem:
ko.merge.fromJS(vm, {
values: [{ text: "Signed-off", count: 90, color: "#5fb5cc" },
{ text: "Submitted", count: 40, color: "#75d181" },
{ text: "Not Submitted", count: 35, color: "#f8a25b" }
],
aggregates: {
count: 250
}
});
Before I started I tested it on one of the top level fields, which seemed to work fine. But if I churn out the same information to the console you can now see that the text field on the first value is no longer observable :(
Hi,
maybe i'm missing if there is a way to initialize an observable array with data, at least for performance improvement. Actually, i'm doing that with a patch like this one below
if (knockoutElement.mergeConstructor.length === 1) {
var arrayElement = new knockoutElement.mergeConstructor(element);
knockoutElement.push(arrayElement);
}
But i'm asking if there would be a cleaner method...
THX in advance, keep up this great work!
I have found that properties with a null value are being treated in the fromJS function in the same way as properties that have a value which is an object that needs to be recursed through. This is because koModel[parameter]=null satisfies the condition below:
else if (typeof (koModel[parameter]) == "object" &&
!(koModel[parameter] instanceof Date) &&
!isArray(koModel[parameter])) {
exports.fromJS(.....
}
Changing the condition to the following solved the problem for me:
else if (koModel[parameter] !== null && typeof (koModel[parameter]) == "object" &&
!(koModel[parameter] instanceof Date) &&
!isArray(koModel[parameter])) {
exports.fromJS(.....
}
I can't seem to get this working with require JS. Wondering if this is a library problem or I'm doing something wrong?
Uncaught TypeError: Cannot read property 'mapping' of undefined knockout.mapping.merge.js:34
(anonymous function) knockout.mapping.merge.js:34
(anonymous function)
I'm using this for my configuration
requirejs.config({
urlArgs: 'v=1.0.1',
baseUrl: '/Scripts',
paths: {
'lib': '/lib',
'app': '../app',
'jquery': [
'//code.jquery.com/jquery-1.11.0.min',
'jquery-1.11.0.min'
],
'jquery-ui': [
'//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min',
'jquery-ui-1.10.4.min'
],
'bootstrap': [
'//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min',
'bootstrap.min'
],
'signalR': [
'//ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.0.2.min',
'jquery.signalR-2.0.2.min'
],
'knockout': [
'//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min',
'knockout-3.1.0'
],
'knockout.mapping': [
'//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min',
'knockout.mapping-latest'
],
'toggles': [
'lib/toggles-2.0.5.min'
],
'knockout.mapping.merge': [
'lib/knockout.mapping.merge.min'
],
},
// define global dependencies
deps: ['jquery', 'knockout', 'knockout.mapping', 'bootstrap'],
// define callback function
callback: function ($, ko, mapping) {
ko.mapping = mapping;
}
});
Then my include
require(['jquery', 'knockout', 'knockout.mapping'], function ($, ko, mapping) {
ko.mapping = mapping;
require(['knockout.mapping.merge'], function () {
var v = ko.mapping.fromJS({ a: "B" });
alert(v.a());
});
});
Are you going to publish new version there? Thx
If you take an object like:
{
title: ko.observable("A")
}
and merge it with an object like:
{
title: "A",
value: "a"
}
Then the newly created value
field won't be observable. It would be great if there was a way to add additional items as observables.
Would you be open to having a flag to do this?
Hi,
Come across a problem with knockout.merge. If an observable has an extender it won't write any value to it. I've included a jsFiddle below to show the behaviour, I would have a go at fixing it myself but I have no clue where to start regarding firing them, I thought they were automatic...
So I only kind-of know what I am doing. I believe I am running into issues with the merge not completing (consistently) before other functions are running. If this was my own function I would add in a callback to be returned when everything has completed. I poked around and tried a few things but am having trouble. Your code is a bit more complex than I am used to following. Any suggestions?
(By the way - this thing is awesome and solved a huge problem I was having - thanks!)
I'm using knockout-3.1.0 and getting an error trying to use mergeFromJS for the first time. Here's what I'm currently doing:
Creating a basic object
var settings = {
mode: "standalone", // mode can be standalone or connected
backgroundColour: {
override: false,
value: "#000000",
overrideValue: "#000000"
},
colour: {
override: false,
value: "#FFFFFF",
overrideValue: "#FFFFFF"
},
fontSize: {
override: true,
overrideValue: "3"
}
}
Adding some computed fields:
// Determine the background colour
retVal.backgroundColour.result = ko.computed({
read: function () {
if (retVal.backgroundColour.override()) {
return retVal.backgroundColour.overrideValue();
} else {
return retVal.backgroundColour.value();
}
},
write: function (val) {
if (retVal.backgroundColour.override()) {
retVal.backgroundColour.overrideValue(val);
}
}
});
// Determine the foreground colour
retVal.colour.result = ko.computed({
read: function () {
if (retVal.colour.override()) {
return retVal.colour.overrideValue();
} else {
return retVal.colour.value();
}
},
write: function (val) {
if (retVal.colour.override()) {
retVal.colour.overrideValue(val);
}
}
});
Loading some settings from local browser storage and trying to merge them:
retVal.updateSettings = function (toUpdate) {
ko.mapping.mergeFromJS(retVal, toUpdate);
}
/** Load the settings from the setting store */
retVal.loadSettings = function () {
// Only update if the store is enabled
if (store.enabled) {
console.log("client settings loaded from store");
// Read the value from the store and
// merge them in using knockout.mapping.merge
var toLoad = store.get("settings");
retVal.updateSettings(this, toLoad);
}
};
At this point I get the error message detailed within the title. Here's a snapshot of the callstack:
Hey guys. I was using the library by trying to merge an object with many observable array properties.
The issue is that the merge actually does an array merge. I was expecting that this library could be used to update an observable with new data.
So, the new array would replace the old one. Version 1.5.2.
I am sure it worked in a previous version (maybe 1.4.2?). Its possibly related to the new merge algorithm for arrays, maybe this:
6299522
Currently the merging is very simple and will work for complex objects assuming there is no sub objects, so for example if you were to have a class called Company and it contained an observable array of Employees, you could not really map the child employees to the company.
So it would be good if there were some sort of system for handling this, be it an extension like with knockout validation.
function SomeContainerObject()
{
this.SomeChildren = ko.observableArray().typedAs(new SomeChildObject);
}
This way when it goes to merge child objects it would be able to create the new child object then assign the values to it. Which would help massively for large object graphs where you need child objects with their own validation etc.
Could you please add a license to the GitHub rep? Preferably MIT as that would then match the Knockout license.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.