LitElement and .bind(this) - lit-element

I'm finding a little confusing sometimes you need to bind the context to a function call and sometimes not. When exactly can you avoid it and when you not?
What's the difference between those lines?
<a #click="${this.handler.bind(this)}">link</a>
<a #click="${this.handler()}">link</a>
<a #click="${this.handler}">link</a>
<a #click="${()=>this.handler()}">link</a>
Also sometimes in the constructor() you need
this.handler = this.handler.bind(this)
to make the function call works, sometimes you not. What's the differences between all those cases?

In the first 4 lines I am guessing you usually wrap them in between ${ and }.
With this mention these 3 lines:
<a #click="${this.handler.bind(this)}">link</a>
<a #click="${this.handler}">link</a>
<a #click="${()=>this.handler()}">link</a>
would be pretty similar in the effect. When you attach an event handler you need to pass a reference to a function/method to call, while the second line:
<a #click="${this.handler()}">link</a>
will most likely just be wrong. That's because you will be calling this.handler() as soon as the rendering is done. The only way it might make some sense it would be if the handler method returns a function.
Going back to the first 3 lines: they will indeed have very similar effect, as in all of them you are passing references to a local method render, but:
the first one doesn't need binding as the method will anyway be
called in this context (but I guess it doesn't hurt either)
the third one adds the definition of an anonymous function as an
event handler, which when called it will invoke this.handler
So the second one is basically the simplest and easiest to read.
When it comes to the need to call bind in some of the cases: that's needed when your method is called from another context. Let's say you pass it as a callback parameter to a method running in another class. When you method will be called there, it will have by default the context of that other object. So you will need to use .bind(this) to make sure that when the method is called in your element's context.
Your method does work, but it's running from another this. So maybe that's why some of the times you don't notice the need to .bind(this). If the method just shows a message, calls some other external service, or anything else that is not part of your object's definition (that doesn't use this.something), it will work without using bind.
UPDATE: in fact I think an event handler will always run in the context of the element that originated that event. I am guessing that lit just does that .bind(this) when we use that #click= syntax, as it would make a lot of sense.

Note that binding directly in templates is generally not a good idea. It can result in performance issues and components re-rendering when they shouldn't.
https://github.com/43081j/eslint-plugin-lit/blob/master/docs/rules/no-template-bind.md
As to why you sometimes need to bind consider this:
#customElement('main-page')
export class MainPage extends LitElement {
#property()
public name = "bob";
render() {
return html`<button #click=${this.clicked}>Click Me!</button>`;
}
clicked() {
console.log("clicked " + this.name);
console.log("this in clicked: " + this)
setTimeout(this.sayHi, 1000);
}
sayHi() {
console.log("this in sayHi: " + this)
alert(`Hello, ${this.name}!`);
}
}
If we click on the button, we get the name logged properly:
But the name isn't shown in the alert:
If we look at this in both functions we get different results:
One is an HTMLElement and the other one is a Window. What this refers to is different once we pass sayHi to setTimeout.
Bind will fix this by making sure that this refers to the right object.
While we could do setTimeout(this.sayHi.bind(this), 1000); and it would fix our issue but it's not very clean and it's error prone. We could bind it in the constructor, but this also isn't much better.
The cleanest way to do it is to directly bind this by using an arrow function instead:
sayHi = () => {
[...]
This notation binds this to the object itself. We then do not need to bind it explicitly ourselves.
Once we do that, both this refer to the right object:

Related

Groovy - Correct way to implement getProperty method

I need to run some code whenever a property value is retrieved, so naturally it made sense to define the getProperty method in my class. This method will get automatically called whenever a property value is retrieved. Here's roughly what I have in my class:
class MyClass
{
def getProperty(String name)
{
// Run some code ...
return this.#"${name}"
}
}
The problem with the above method occurs when someone tries to make the following call somewhere:
MyClass.class
This call ends up in the getProperty method looking for a property named "class", however, there is not actual property named "class" so we get a MissingFieldException.
What would be the correct way to implement running code whenever a property value is retrieved and deal with these kind of situtations.
Best is not to have a getProperty method if not needed. If you need one and you want to fall back on standard Groovy logic, then you can use return getMetaClass().getProperty(this, property), as can be found in GroovyObjectSupport. This will cover more than just fields.
This seems to be a common problem with this method. Map has the same issue. The developers of groovy got around the problem with Map by saying you need to use getClass() directly.

How do I spoon feed an IObservable from procedural code?

Most sample codes around Reactive Extensions revolves around how you compose logic and operators on the sequence.
The parts around Observable generation focus around "FromEventPatter","FromAsynch" etc.
IObservable<string> observableHotStatus = ??;
foreach (var task in todo)
{
//Process task;
//Post status message into observable; How do I do this?
}
In short, I want an object that I can post into, like an ActionBlock, Action (of T) or something like that.
What's the easiest way to achieve this?
Edit:
Examining your code more closely, I'd recommend using Observable.Create. Even though it only returns a cold observable, you can apply the Publish operator to the generated observable to make it hot.
And if by task you're actually referring to Task<T>, then you can use an overload of Observable.Create that allows you to define an async iterator. For example:
IObservable<string> statuses = Observable.Create<string>(
(observer, cancel) =>
{
foreach (var task in todo)
{
cancel.ThrowIfCancellationRequested();
await task;
observer.OnNext("Status");
}
});
Previous Answer:
You could use one of the following types, but I suggest reading To Use Subject or Not To Use Subject first before making your decision.
Subject<T>: General purpose, "event"-like, hot observable. Calling OnNext is like raising a classic .NET event.
BehaviorSubject<T>: Generally used as the backing field for a property, it represents an observable sequence of change "events". Whenever an observer subscribes, it receives the current value immediately, followed by all changes to the property. You can extract the current value at any time from the Value property; e.g., within your property's getter. Call OnNext within your property's setter and you don't have to keep a duplicate backing field. It's also Rx's version of a continuous function and it's the only FRP-like thing you'll find in Rx, if my understanding of FRP is correct.
ReplaySubject<T>: Generally used as an historical buffer of "events", it represents an observable sequence of values beginning with the values that have been missed by an observer, whenever an observer subscribes. You can control how far back values are buffered; it's like a sliding window over the history of values. You rarely have to use this type. In most cases, the Observable.Replay operator will do.
AsyncSubject<T>: Generally used to capture the results of hot, asynchronous functions like Task<T>. You rarely have to use this type. In most cases, Observable.FromAsyncPattern or Task-conversion operators will do.

How to detect if an element is "Stale" in Geb?

I'm trying to detect if a module has gone "stale" in Geb. That is, if using will throw:
org.openqa.selenium.StaleElementReferenceException
The below code seems to work, but I feel like its excessively hacky (I'm just calling any arbitrary method on module (toString() seemed like a decent choice) and checking if it throws the stale element exception.
static boolean isStale(Module module)
{
boolean isStale = false
try {
module.toString() // arbitrary method call
} catch (StaleElementReferenceException e) {
isStale = true
}
return isStale
}
Is there a cleaner way to do this?
If you are trying to detect page changes, however arbitrary those pages are then I would probably tackle it the other way around - detecting the new content and not the stale content. First, you have to find something (an element or a state of an element) that you can use in your at checker to detect that the new page has "loaded". Then you would execute the page changing action and wrap an at checker verification inside of a waitFor {} call. This should be more reliable than your current approach, especially because Geb doesn't cache any content elements by default.

Best practices for callbacks within a scope

Typically, in "constructor" you subscribe to events with lambda-functions:
function Something(){
this.on('message', function(){ ... });
}
util.inherits(Something, events.EventEmitter);
This works well but extends bad. Methods play better with inheritance:
function Something(){
this.on('message', this._onMessage);
}
util.inherits(Something, events.EventEmitter);
Something.prototype._onMessage = function(){ ... };
What are the best practices to keep these event handler functions?
if i understood the question correctly then i think that it depends on how much open for changes you are willing to be.
your second example opens the option for subclasses (or, actually, any class) to override the handler's code, which isn't necessarily a good thing.
the first example prevents overriding but at the cost of having anonymous functions (sometimes containing a lot of code) inside your constructor. however, this code can be extracted to another private function (not on the prototype, just a regular function inside the module's file).
the open-close principal deals with this kind of questions.

Enumerate events/eventListeners for a WinJS object

I'm using pure WinJS for a project (No jQuery) and have run into a requirement that has me stumped.
Let's say I have a DOM element called 'bob' (although this might not necessarily be a DOM element). To attach an event listener, I would do this:
bob.addEventListener('click', function ()
{
// Some code goes here
});
There is nothing stopping me from adding lots of event listeners to 'bob', even for the same event names (which is fine as they are just queued) - herein lies the rub!
I need to be able to enumerate the events/listeners that are attached to a given object so I can selectively replace or tweak some of them at runtime.
Any thoughts on how to acheive this?
It's not possible to enumerate events added using addEventListener. The way you're adding the event is not recommended (at least by me :). You're using addEventListener but then using an anonymous method. If you do that then you'll never be able to remove that event because you don't have a handle to it. I would recommend creating your function and then assigning the named function (myelement.addEventListener("event", myfunction)). Each time you add an event to your element, just add it to a collection (an array hanging off the element itself) and then you'll have your list of events.
It turns out that you can, in some circumstances, enumerate attached event listeners.
If you are using the 'Events' Mixin on an object, then once you have called one of the mixed-in methods (addEventListener, removeEventListener or dispatchEvent), your target object will gain a property called _listeners (assuming it doesn't already exist).
For a practical example, here's a function that counts the number of attached event listeners for an object that uses this mixin:
/*
* Counts the number of attached listeners
*/
countListeners: function()
{
var count = 0;
if (this._listeners)
{
var key;
for (key in this._listeners)
{
if (this._listeners.hasOwnProperty(key))
{
count++;
}
}
}
return count;
}
Hope this helps someone!
G

Resources