Giter Site home page Giter Site logo

ziadj / knockoutjs-reactor Goto Github PK

View Code? Open in Web Editor NEW
74.0 74.0 23.0 325 KB

Recursively tracks changes within a view model no matter how deeply nested the observables are or whether they are nested within dynamically created array elements.

License: Other

JavaScript 100.00%
centralized children hierarchical-models javascript knockout listener recursive subscribe subscription watch

knockoutjs-reactor's People

Contributors

bago avatar dependabot[bot] avatar jakiestfu avatar jsearles avatar ziadj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knockoutjs-reactor's Issues

Tested for Possible Memory Leaks

Have you tested for possible memory leaks since you subscribe to each child node in a list and below? If nodes are removed are their subscriptions cleaned up in such a way that they will not hold on to memory?

_fieldName not set?

Maybe it's my misunderstanding (or lack of documentation), but I cannot get changed field name in the _fieldName.

Consider this simple fiddle: http://jsfiddle.net/y0ygaszL/1/

Whenever I change a scalar property ("set prop" button), _fieldName is not set neither on child nor on the parent.

When I change width or height property of array element, then array field name is correctly reported in the parent, but the property name itself is still missing on the child.

Also, when array element is removed ("remove" button), the watch callback is not invoked at all.

Would you please comment?

Keep notifying changes for replaced objects

var subModel = {
  c: ko.observable(1),
  d: ko.observable(0)
};

var subModelB = {
  e: ko.observable(0),
  f: ko.observable(1)
};

var model = {
  a: ko.observable(1),
  b: {
    g: ko.observable(0),
    h: ko.observable(0),
  },
  sub: ko.observable(subModel),
};

var w = ko.watch(model, { depth: -1, oldValues: 1, mutable: true, tagFields: true }, listener);

model.sub(subModelB);
subModel.c(4); // this is a change in a model being removed by the original tree, but still the listener is notified with this change.

Some "unwatch" is not working correctly.

Bad parents in the notifications when sub-objects are replaced

var subModel = {
  c: ko.observable(1),
  d: ko.observable(0)
};

var subModelB = {
  e: ko.observable(0),
  f: ko.observable(1)
};

var model = {
  a: ko.observable(1),
  b: {
    g: ko.observable(0),
    h: ko.observable(0),
  },
  sub: ko.observable(subModel),
};

var w = ko.watch(model, { depth: -1, oldValues: 1, mutable: true, tagFields: true }, listener);

model.sub().c(4); // this is notified correctly

model.sub(subModelB);
model.sub().e(4); // this is notified with the wrong number of parents

Once you replace an observable object the new notifications have one more "parent" that is not expected.

KO Reactor / KO Undo Manager compatibility (context is not a function)

I am not sure where this issue belongs/must be fixed, so I'm opening in both repositories, since @bago is KO Reactor contributor and KO Undo Manager author.

According to KO Reactor (link), it supports a context option, which is undocumented. Looking at its usages in assignWatcher function, context should be a function.

However, KO Undo Manager is building an empty object (link) as context and is passing it to KO Reactor (link).

This leads to a TypeError: context is not a function error.

At this point, there are 2 options:

  • KO Undo Manager passing an empty function instead of empty object, which is what KO Reactor expects
  • KO Reactor checking if context is a function before executing it, e.g. typeof context === 'function' && context(returnValue) instead of context(returnValue).

Additionally, it might help if KO Reactor's context option is documented to indicate how it should look like.

I am happy to contribute with a PR if needed, I'm just not sure what's the correct way to handle this. Both options would be backwards-compatible.

support for _fieldPath/childPath and "observable Objects"

Hi, I'm the ko-undomanager author and I have a feature request.. I'm willing to implement it but I'd like to have some hint from you (and to know if you think my needs are "general purpose" or not).

In the undomanager I currently keep a stack of functions that have references to the "child" and the previous value, so that they simply set the value when you "undo". Now I have to improve it so that I don't keep references to live objects because it keeps "removed" objects live and this break other things. So I'd like to change it so that I remember only the "tree-path" (as a string) and the value (again as a primitive variable/object): e.g: { path: "root.object.array[3].property", oldvalue: "5" }. This would also allow me to put the undo/redo stack on the wire (this is serializable) and do smart things.

Now my issues are:

  1. _fieldName on the parents doesn't work when you use observableObjects. I have models like this one:
    model: {
    objProp: ko.observable(
    prop1: ko.observable(prop1Val),
    prop2: ko.observable(prop2Val)
    ),
    obj2Prop: ko.observable(
    prop1: ko.observable(prop1Val),
    prop2: ko.observable(prop2Val)
    ),
    }
    Currently the "_fieldName only applies to simple Objects or Array and in my case it finds "Functions" (observable) where it only supports Objects or Array.

  2. _fieldName only applies to parents and doesn't tell me the "index" in case my child is in array... so if I loop in the parents I can build "root.object.array.property" but not "root.object.array[3].property" that I need to be able to find again the right object when I execute undo. What about implementing an option so that the watching function also receive the childPath (relative to the root of the watch( and inlcuding indexes for the arrays?

Won't wrap a property when it has a null value

At around line 176 in watchChildren, there is an if (sub) statement that prevents any wrapping of a property if the property of the object is null. I'm not sure if this is desired behavior in some cases but in my case it was not. The property was null but when bound to a form, changes that the user made weren't invoking my event handler. I removed the if() statement and it worked as I'd expect. And no errors.

So I think we should remove the if (sub) statement so that any changes made to the property value in the UI generate a change event.

hide option still watching

Hi,
In the readme it's mentioned that, to unwatch any observable we can simply pass {hide: path.of.observable} as an option. But when I do this it still watches for the item I specified in the hide option.
Not sure if I'm doing this right but here's a rough fiddle which I put together to check the hide option.

Thanks for the plugin. Really impressed by how much it does with such little code. 👍

Uncaught Subscriptions field (.K) not defined for observable child Error only when using knockout.debug

I have knockout 3.4.1 debug and reactor 1.3.7 and I get this error only when using debug version of knockout.

Uncaught Subscriptions field (.K) not defined for observable child
disposeWatcher @ knockout.reactor.js:233
watchChildren @ knockout.reactor.js:144
(anonymous) @ knockout.reactor.js:179
objectForEach @ knockout-3.4.0.js:62
watchChildren @ knockout.reactor.js:161
(anonymous) @ knockout.reactor.js:249

AMD module support

I am trying to load this library using requireJS but It keeps failing with "Uncaught ReferenceError: ko is not defined ".

Any ideas what might cause this?

Reactor recursion doesn't work

The following test case for recursion doesn't appear to work (ko 2.2.1, ko.mapping 2.4.0):

var data = "{\"id\":1,\"items\":[{\"id\":1},{\"id\":2}]}";

var model = ko.mapping.fromJSON(data);

ko.watch(model, { recurse: true }, function () {
    alert('Reactor');
});

// Change the data
model.id(2); // Reacts OK
model.items()[0].id(2); // Does not react

Monitoring arrays?

I've found this github project following the post in http://stackoverflow.com/questions/10622707/detecting-change-to-knockout-view-model , and I'm interested in the case where I need to monitor an array both for changes in the observableArray itself (adding/removing items) and the changes in the items of the array. The array items are simple objects, and some of their properties are also observables.

I don't need to monitor the whole model, just this one array.

I've tried using the "latest" source file in the github, and my code looks like this:

ko.watch(mymodel.list, { recurse: true }, function() {
  alert("changed");
});

... but nothing happens.

Is this possible and what would the code look like?

Issue with KO 3.3.0 and the minified reactor

The min.js is missing a "break" after the 3.3.0 switch "match" so it uses the ".K" variable for both 3.3.0 and 3.4.0... The "non-minified" version works fine.

So it seems something gone wrong with the minification process.

How can we reset it?

Sorry I'm new to knockout.
I have a view in read mode and an Edit button. When the user clicks it then I display an Edit view, start to watch my viewmodel for change and display a Cancel and a Save button.
If the user click the Cancel button I would like to reset the watching.
How could it be possible?
Thank you!

New release?

Hi ZiadJ, what about making a new release? It's a long time since the last proper release (1.3.0) and a lot of fixes/changes.

If you need help I can do that if you give me privileges to the project.

adding .watch(false) -- Uncaught ReferenceError: context is not defined -- knockout.reactor.js:31

Not sure if this is a bug in the code or and issue with the documentation? I don't seem to be able to get the .watch(false) to work.

I have a list item that when clicked gets a 'selected=true' set, this is my code that bugs out:

self.selected = ko.observable(false).watch(false);
self.onClick = function(item) { root.unselect_all(); self.selected(true) };

Am I doing it wrong? Or is this a bug?

Bower Accessible

It would be nice to have this as a bower module so that we can pull this down directly into our projects. Any plans for this in the future? If not, I could make a pull request to do it.

syntax

Interesting plugin. But I don't understand the ko.observable().watch syntax. By adding watch to ko.subscribable.fn, you make it a method of every observable. So if you have item = ko.observable();, then you could do item.watch(...);, but that wouldn't mean what it seems to. If you want to make it part of ko.observable, it should just be ko.observable.watch.

Cannot ignore observable arrays

It's currently not possible to ignore an observable array within a hierarchy. (The code-path for arrays never does this check.)

Also instead of having a "beta" file would you consider making a separate alpha branch?

Basic functional test suite

I have hard times figuring out issues in the library and understanding if some code was a feature or a bug.

This library offer a big set of options and I cannot check all of them, but at least I can add some tests for my own use cases. Time and more use case will help improving it.

Automatically watch new objects recursively

I have a deep JSON object that a wrap to nested observables through knockout.wrap (I don't think this is a variable for this issue, but better safe than sorry).

When I do
viewModel.myObject(newObject);
then the observable properties of newObject are not automatically watched by reactor.

Is this something expected? I see other "mutations" for the array are tracked but this one is not.

Deleted items are not unsubscribed

I faced with issue that change event is fired for deleted item. And it caused some unpredictable behavior in my application. Looks like I found a reason for it. I found a place in your code:
(line 145) var subsc = child._subscriptions;
And then you try to delete some subscriptions. As I understand, _subscriptions is knockout stuff, but I have minified version of it, so _subscriptions is underfined and, as result, subscription were not deleted. Also you try to delete subscriptions within ko.utils.arrayForEach and it caused one more issue, so I changed it with for loop.

My issue. I have an object:

{
...
Exits: [
    ...,
    {
        ...
        Next: {
            TargetId: 'value',
            Anchor: 'value2'
        }
        ...
    },
    ...
]
...
}

I deleted an object from Exits array and then added it. When I try to change value of TargetId or Anchor I have two change events instead of one.

KO version check for minimized propery names

disposeWatcher uses "child.H || child._subscriptions;"

For every knockout version the minimized name changes breaking that code.

in 3.0.0 the minimized name is "F"
in 3.1.0 it is "H"
in 3.2.0 it is "M"
in 3.3.0 it is "G"

So it seems the current code is only "fully" compatible with 3.1.0.

How to "unwatch" / stop watching?

Is there a way to stop watching a tree / unwatch the tree?

I see the code has "unwatch" / "dispose" methods but they seems "internal" and not public: am I missing anything?

"un-watch" functionality...

Hello,
I do not see in your documentation the ability to "un-watch" a view model. Does this automatically occur when ko.cleanNode(...) is called?

Thanks,
Jim

Multiple watch break on dispose

var options = { depth: -1 };
var a = ko.watch(model, options, listener);
var b = ko.watch(model, options, listener2);
a.dispose();

listener2 is not called anymore.

I saw that "context" equals "ko" in the internal checks, for both calls.
I thought I could call the 2 watch with different context but I see the code somewhere uses context(returnValue); so context have probably some meaning that I am missing.

Can you document the "context" stuff or explain me how can I have 2 indipendent watchers?
I use knockout-reactor for a custom function in my project, but the same project also uses my undomanager: when I dispose the first watch the undomanager stops working.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.