I kind of understand how change detection works in Angular 2 but I'm really struggling to transfer/change my AngularJS methods over to NG2 regarding change detection.
Imagine I have a component that takes a single #Input() anObject and has a single function, logAllProperties() which, for arguments sake, logs all the properties to the console.
All I want to do is to call logAllProperties() every time anObject changes in anyway whatsoever.
I understand that treating the object as immutable (either with an external library like Immutable.js or by enforcing that the entire object changes even for a minor property change) will trigger ngOnChange but is there anyway to call a function whenever a change takes place aside from these or using DoCheck which I understand is potentially extremely inefficient.
As well as "is there a way", what is the correct way to do something like this? I'm new to Angular2 so I'm more than happy to learn the right way if Immutable and Observables are the way to go.
Thanks in advance
The straightforward way of executing an action everytime anObject change is by using a setter or ngOnChange (see Fals' answer).
Using immutable objects witch a change detection strategy of OnPush is a way to improve change detection performance. This is not the most obvious use of change detection in Angular.
For a complete explanation I suggest you read this really good article and if you have some time (45 minutes) you can check this video by the author of the article here
From there, you should have a good understanding of what's going on.
#input decorator is denoted your component is expecting to get some data from its parent which will be caught at that property
same way #output is the decorator in angular2 wherein parent component you can catch something from child.
Internally it uses observable and I don't think it's immutable.
ngrx provides a redux type immutable mechanism where every state is remembered and you can go back to them as well.
Observable and ngrx are running in parallel now.
I found out in our projects that using set works well in some cases, but others cases that need sync between components could be troubling, then we are using ngOnChange for those cases. Here's an example.
#Input() set myProperty(myProperty: MyPropertyType) {
if (myProperty) {
this.logService.log(myProperty);
}
this._myProperty = myProperty;
}
private _myProperty: MyPropertyType= new MyPropertyType();
The thing about Angular2 new lifecycle still confuse, and the documentation samples doesn't fit most of the real world cases.
Related
With a custom component, you can use the static get observedAttributes() in your web component to specify what attribute changes trigger the attributeChangedCallback() lifecycle method.
However, it seems you can also achieve a similar callback by using the MutationObserver API, documented here, with {attributes: true} to watch all attribute changes, or to refine it more, using a {attributeFilter: Array<string>}.
What's the difference in using the two different methods? Seems like the MutationObserver offer much more flexibility, while the first method is equivalent to having defined an attribute filter.
Yes, minor functional differences.
But MutationObserver takes a lot more boilerplate, and you can't ask the MO which attributes are observed.
It is kinda like saying Why do we need Map, when everything can be done by extending Array
I don't have data, but would say observedAttributes is highly optimized. MO is taking a sledgehammer to drive in a nail.
But as you commented; observedAttributes doesn't give you dynamic attributes.
A decorator adds additional functionality to an object by "wrapping" around the original value.
Is there a name for an object or function that ingests a pre-constructed object and adds additional functionality to it via mutation?.
Example:
function mutatesObjects(target) {
target.additionalFunctionality = "I've been mutated!";
}
This is similar to a contrcutor or factory except that it is adding functionality to an object that was already created.
Is there a name for this pattern?
Depending on the purpose for this change, Monkey Patching might apply.
"A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program)."
I would suggest Plugin name as a reference to jquery plugins.
But I also think this is actually an anti-pattern in most cases. This not only breaks the encapsulation (one of the main concepts in OOP), it goes even beyond it and changes object functionality.
Imagine a simple case where you do something like:
doSomething(object)
In the best case you can hope the object state was not changed. In the worse case you can suspect that it was mutated and it's state changed.
It's really unexpected if you get something completely different with new methods or properties.
But of course, there can be good usages (like jquery plugins).
I am struggling with a problem that keeps cropping up when working with the KnockoutJS framework and MVVM in general. There are times when a property on a specific item in a collection changes and because of that change, I need to affect all the other items in that same collection. In all languages and patterns, an object isn't supposed to "know" anything about the collection it's in, but I find myself needing to break that rule often to get certain kinds of logic to work.
I have created a contrived example of what I'm talking about to demonstrate the hacky sort of way I've been solving this problem. I'm hoping someone with more experience can weigh in and show me the better way to do this.
JSFiddle Contrived Example
I don't know whether this is the "recommended" approach, but I will offer my advice of how I would tackle this issue. I am not a MVVM expert (though I've written quite a few KnockoutJS apps), but I think some OOP principles will be more than enough to help here.
So first let's discuss the current state of things...
Your approach, as you correctly observed (knockout pun unintentional!), is not ideal - the Person objects are aware not just of their siblings (even if indirectly via a subscription) but also the parent object to which they are subscribing - Your Person type is subscribed to changes on the parent. Not only does this make your Person object unusable outside of this scenario, it also gives each instance too much responsibility (violating the Single Responsibility Principle) and each instance is subscribed to changes on every other instance, which is of course wasteful!
So what's the solution?
To me the ideal place to put this kind of logic is on your parent object (i.e. your view model). Your view model already has knowledge of it's child objects, so why not put the functionality there? This would make your Person type reusable elsewhere (OK so it has observables, so it's tied to KO at the moment, but this can be overcome with the Mapping plugin) and relieves it of the responsibility of managing its siblings.
But still this means that you have tight coupling between parent and child - not what we want in OOP! To overcome this, you can adopt a pub/sub (observer) pattern and have your Person type publish a message whenever something changes, then you can let a subscriber (e.g. you view model) decide how to respond to this event. You need not necessarily use knockout's pub/sub offerings either, any pub/sub implementation will do. Though you may as well take advantage of what KO offers, so I would point you in the direction of these extensions/helpers to ease things a little: http://www.knockmeout.net/2012/05/using-ko-native-pubsub.html
Hope I've been of help :)
Unless I misunderstood your scenario, you could use computed observables that update on the fly automatically.
First, I figured the 'underage' property flag for each person would just be a calculation of their age compared to a min. age. e.g. 19.
Second, You can also use a computed observable to do an aggregate flag for all users.
Lastly, I wouldn't necessarily agree that this is a parent/child relationship. These are just properties of the view model specific to the page.
Check out this example that uses computed's for both cases.
http://codepen.io/anon/pen/ufKCo
After dabbling with javascript for a while, I became progressively convinced that OOP is not the right way to go, or at least, not extensively. Having two or three levels of inheritance is ok, but working full OOP like one would do in Java seems just not fitting.
The language supports compositing and delegation natively. I want to use just that. However, I am having trouble replicating certain benefits from OOP.
Namely:
How would I check if an object implements a certain behavior? I have thought of the following methods
Check if the object has a particular method. But this would mean standardizing method names and if the project is big, it can quickly become cumbersome, and lead to the java problem (object.hasMethod('emailRegexValidatorSimpleSuperLongNotConflictingMethodName')...It would just move the problem of OOP, not fix it. Furthermore, I could not find info on the performance of looking up if methods exist
Store each composited object in an array and check if the object contains the compositor. Something like: object.hasComposite(compositorClass)...But that's also not really elegant and is once again OOP, just not in the standard way.
Have each object have an "implements" array property, and leave the responsibility to the object to say if it implements a certain behavior, whether it is through composition or natively. Flexible and simple, but requires to remember a number of conventions. It is my preferred method until now, but I am still looking.
How would I initialize an object without repeating all the set-up for composited objects? For example, if I have an "textInput" class that uses a certain number of validators, which have to be initialized with variables, and a class "emailInput" which uses the exact same validators, it is cumbersome to repeat the code. And if the interface of the validators change, the code has to change in every class that uses them. How would I go about setting that easily? The API I am thinking of should be as simple as doing object.compositors('emailValidator','lengthValidator','...')
Is there any performance loss associated with having most of the functions that run in the app go through an apply()? Since I am going to be using delegation extensively, basic objects will most probably have almost no methods. All methods will be provided by the composited objects.
Any good resource? I have read countless posts about OOP vs delegation, and about the benefits of delegation, etc, but I can't find anything that would discuss "javascript delegation done right", in the scope of a large framework.
edit
Further explanations:
I don't have code yet, I have been working on a framework in pure OOP and I am getting stuck and in need of multiple inheritance. Thus, I decided to drop classes totally. So I am now merely at theoretical level and trying to make sense out of this.
"Compositing" might be the wrong word; I am referring to the composite pattern, very useful for tree-like structures. It's true that it is rare to have tree structures on the front end (well, save for the DOM of course), but I am developing for node.js
What I mean by "switching from OOP" is that I am going to part from defining classes, using the "new" operator, and so on; I intend to use anonymous objects and extend them with delegators. Example:
var a = {};
compositor.addDelegates(a,["validator", "accessManager", "databaseObject"]);
So a "class" would be a function with predefined delegators:
function getInputObject(type, validator){
var input = {};
compositor.addDelegates(input,[compositor,renderable("input"+type),"ajaxed"]);
if(validator){input.addDelegate(validator);}
return input;
}
Does that make sense?
1) How would I check if an object implements a certain behavior?
Most people don't bother with testing for method existance like this.
If you want to test for methods in order to branch and do different things if its found or not then you are probably doing something evil (this kind of instanceof is usually a code smell in OO code)
If you are just checking if an object implements an interface for error checking then it is not much better then not testing and letting an exception be thrown if the method is not found. I don't know anyone that routinely does this checking but I am sure someone out there is doing it...
2) How would I initialize an object without repeating all the set-up for composited objects?
If you wrap the inner object construction code in a function or class then I think you can avoid most of the repetition and coupling.
3) Is there any performance loss associated with having most of the functions that run in the app go through an apply()?
In my experience, I prefer to avoid dealing with this unless strictly necessary. this is fiddly, breaks inside callbacks (that I use extensively for iteration and async stuff) and it is very easy to forget to set it correctly. I try to use more traditional approaches to composition. For example:
Having each owned object be completely independent, without needing to look at its siblings or owner. This allows me to just call its methods directly and letting it be its own this.
Giving the owned objects a reference to their owner in the form of a property or as a parameter passed to their methods. This allows the composition units to access the owner without depending on having the this correctly set.
Using mixins, flattening the separate composition units in a single level. This has big name clash issues but allows everyone to see each other and share the same "this". Mixins also decouples the code from changes in the composition structure, since different composition divisions will still flatten to the same mixed object.
4) Any good resources?
I don't know, so tell me if you find one :)
I am working on a CoffeeScript game engine for Html5 canvas. I came up with the "cool" idea to utilize mixins after I checked a very neat CoffeeScript implementation. I thought, it may be a very cool idea to reduce the various hierarchy of objects that game objects usually provide, by developing a set of mixin-based components, each of which has a very specific functionality. Then, when developing an actual game, one could build unique game objects on the fly by basically starting from one component and mixing it with a bunch of other components. This reduces the hierarchies and allows for frequent changes.
Then I thought about the possible collisions that might come up, for example having a few components define a method with the same signature. Now, I am not as excited as before.
What should I do? Is this a good way? I still like it, especially because of JS' underlying prototype mechanism, which allows for such an easy way to combine stuff on the fly.
You're talking about an entity component system. There are a couple written in JS; the most popular is Crafty, which is big but worth looking at. I recently wrote one in CoffeeScript (just for funsies; will probably never release it).
A few notes about collisions:
So first, the problem may be worse than you think: collisions will happen if two methods have the same name; JS doesn't differentiate function signatures. It also might not be so bad: why don't you just create a namespacing convention, where each behavior (meaning method) is named after the component it belongs to, like burnable_burn?
To take a step back though, mixins aren't the only way to build this - behaviors (i.e. things a component can do) don't have to be methods at all. The motivating question I ask is, how do you trigger a behavior? For example, you might do:
if entity.hasComponent "burnable" #hasComponent provided by your framework
entity.burn()
But that doesn't sound right to me; it creates a weird coupling between what's happening in your game and what components you have, and it's awkward to check if your entities implement the relevant component. Instead, I'd like behaviors to be listeners on events:
entity.send("applySeriousHeat") #triggers whatever behaviors are there
And then have your component do whatever it needs to do. So when you add a component to an entity, it registers listeners to events. Maybe it looks like (just sketching):
register: (entity) -> #called when you add a component to an entity
entity.listen "applySeriousHeat", -> #thing I do when this event is sent to me
#do burnination here
To bring that point home, if you do that, you don't care about collisions, because your behaviors don't have names. In fact, you want "collisions"; you want the ability to have more than one component respond to the same event. Maybe it burns and melts at the same time?
In practice, I used both setups together. I made entity.addComponent mix in the component's functions, since it's occasionally convenient to just call a behavior as a method. But mostly, the components declare listeners that call those methods, which helped with decoupling and reduced the awkwardness of having to use scoped names, since I don't call them directly in most cases.