Angular2: What does binding event to 0 mean? - javascript

I am learning Angular 2 from the official guide. I came across the following piece of code.
#Component({
selector: 'loop-back',
template: `
<input #box (keyup)="0">
<p>{{box.value}}</p>
`
})
export class LoopbackComponent { }
As you see in the template keyup event is bound to 0, (keyup)="0". I don't understand what it means when an event is bound to a number. In doc it says that
code binds the keyup event to the number 0, the shortest template statement possible. While the statement does nothing useful, it satisfies Angular's requirement so that Angular will update the screen.
I delved over internet also but could not find any explanation regarding to binding events to number. Can anyone please help me on this? Thanks.

(keyup)="0"
means, when that event happens, then return 0, which is quite equivalent to "do nothing". There is no shorter way of expressing that, except not adding any event binding at all.
The event binding is used in that example to cause change detection to run, which is by default run every time an event handler was called.
Without the event binding, there is no event handler and Angular won't run change detection, which will cause {{box.value}} to not update the value.

It was not clear for me as well, because I thought that Angular triggers the change detection on any asynchronous event. For example Angular University states that:
The following frequently used browser mechanisms are patched to support change detection:
all browser events (click, mouseover, keyup, etc.)
setTimeout() and setInterval()
Ajax requests
But it's not a whole truth, because official documentation says that:
Angular updates the bindings (and therefore the screen) only if the app does something in response to asynchronous events, such as keystrokes. This example code binds the keyup event to the number 0, the shortest template statement possible. While the statement does nothing useful, it satisfies Angular's requirement so that Angular will update the screen.
So apparently an asynchronous event must be handled in the application in order to trigger the change detection, hence (keyup)="0"

Related

Angular double curly braces expressions being executed multiple times on mouse down and up

In our Angular app, given code like the following:
<div>{{ aGetProperty }}</div>
<div>{{ aMethod() }}</div>
Whenever I click anywhere on the page, these expressions are evaluated multiple times. That is, if I put a console.log('hello') in aMethod, every time I press down on either the left or right mouse button, hello is outputted to console multiple times and again multiple times on mouse up.
Anyone know what could be causing this issue? I have not bound any click, mouse up/down events for the component or anything above it (as far as I can tell). Thanks.
Angular actually patches the browsers's low-level API: for example the addEventListener is patched to check for changes in DOM and rerender the view. Thus, when you click on the DOM elements Angular will run change detection and your method calls in DOM will get executed. In other words: it's a bad practice to bind methods from DOM - unless it's explicitly an on/click event - because the method will get executed on each change detection in lifecycle. Of course, sometimes you'd indeed want some of your methods to fire on each change, but make sure that's exactly what you want.

How to get DOM events triggered by jquery using observables

I am little confused,
I am using bootstrap theme in angular. Some one has written tab implementation as provided by bootstrap. But there is problem, it is in JavaScript. so events such as bs.tab.show are not captured by using observables. Observable.fromEvent does not run on subscription. The method used to trigger DOM event in bootstrap library is $(element).trigger('bs.tab.show', ...)
My basic understanding is whenever any event such as click, hover or in my case bs.tab.show is triggered from DOM, event goes in event stack, and observables is using same event stack to read events.
Could anyone point out difference?
It appears you may have the name of the events wrong.
If I use fromEvent with show.bs.tab instead, the event is triggered.
fromEvent(elem, 'show.bs.tab').subscribe(() => {
console.log("Heard")
})
Here is a StackBlitz demo

Alternative to Falsely Triggering an Event

TLDR Below
JS Fiddle To Demo
I've been really involved in recreating the tools that are foundations of premiere JS Libraries to better improve my skills. Currently I'm working on functional data-binding a la Angular.
The idea of data-binding is to take data and bind it to elements so that if manipulated all elements subscribed will change accordingly. I've gotten it to work but one thing I hadn't considered going into it was the issue with innerHTML vs value. Depending on the element you need to change one or the other( in the demo above you'll see that I needed to specifically single out the button element in a conditional statement because it has both, but that's kind of a fringe case )
The issue is that in order to capture a SPAN tag update I needed to trigger an event to happen, and the easiest one to manipulate for Text Boxes/Textareas was 'keyup'.
In my function then, if you pass in an element with no value property we assume you're going to be updating innerHTML, and we setup an observer to determine if the element ever mutates, and if it ever does, the observer will emit a 'keyup' event.
if (watchee.value == void(0)) {
var keyUpEvent = new Event('keyup');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
watchee.dispatchEvent(keyUpEvent);
});
});
observer.observe(watchee, {
childList: true
});
}
Now it may just be my paranoia, but it seems like I might be tunneling into a can of worms by faking 'keyup' on an element that doesn't natively have that support.
TLDR:
I'm curious if there's an alternative way to make, a.e. a span tag reactive other than faking a 'keyup'/'keydown'/'change' event? For instance, is there a way that I can make my own pure event(by pure I mean not reliant on other events) that checks if innerHTML or value has changed and then performs a function? I know that this is probably possible with a timer, but I feel like that might hinder performance.
EDIT: just an aside. In the demo the function called hookFrom works by taking a DOM node and returning a function that will take the receiving dom node and continues to return a function that will take additional receiving dom nodes. :
hookFrom(sender)(receiver);
hookFrom(sender)(receiver)(receiver2);
hookFrom(sender)(receiver)(receiver2)(receiver3)(receiver4)...(receiver999)...etc
JS Fiddle To Demo (same as above)
There is nothing inherently wrong with creating a similar event on a DOM node that doesn't natively have that functionality. In fact this happens in a lot of cases when trying to polyfill functionality for separate browsers and platforms.
The only issue with doing this sort of DOM magic is that it can cause redundancy in other events. For instance the example given in this article: https://davidwalsh.name/dont-trigger-real-event-names shows how a newly minted event using the same event name can cause problems.
The advice is useful, but negligible in this specific case. The code adds the same functionality between text boxes, divs, spans, etc... and they are all intentionally handled the same way, and if the event would bubble up to another event, it would be intentional and planned.
In short: There is a can of worms that one can tunnel into while faking already explicitly defined event names, but in this case, the code is fine!

In React, what's the difference between onChange and onInput?

I've tried searching around for an answer to this, but most of them are outside the context of React, where onChange triggers upon blur.
In performing various tests, I can't seem to tell how these two events are different (when applied to a textarea). Can anyone shed some light on this?
It seems there is no real difference
React, for some reason, attaches listeners for Component.onChange to the DOM element.oninput event. See the note in the docs on forms:
React docs - Forms
There are more people that are surprised by this behavior. For more details, refer to this issue on the React issue tracker:
Document how React's onChange relates to onInput #3964
Quote from the comments on that issue:
I don't understand why React chose to make onChange behave like onInput does. As fas as I can tell, we have no way of getting the old onChange behaviour back. Docs claim it's a "misnomer" but not it isn't really, it does fire when there's a change, just not until the input also loses focus.
For validation, sometimes we don't want to show validation errors until they're done typing. Or maybe we just don't want a re-render on every keystroke. Now the only way to do that is with onBlur but now we also need to check that the value has changed manually.
It's not that big of a deal, but it seems to me like React threw away a useful event and deviated from standard behaviour when there was already an event that does this.
I agree 100% with the comment... But I guess changing it now would bring more problems than it solves since so much code had already been written that relies on this behavior.
React is not part of the official Web API collection
Even though React is built on top of JS, and has seen a huge adoption rate, as a technology React exists to hide a whole lot of functionality under its own (fairly small) API. Once area where this is obvious is in the event system, where there's a lot going on under the surface that's actually radically different from the standard DOM event system. Not just in terms of which events do what, but also in terms of when data is allowed to persist at what stage of the event handling. You can read more about that here:
React Event System
There is no difference
React does not have the behaviour of default 'onChange' event. The 'onChange' which we see in react has the behaviour of default 'onInput' event. So to answer your question there is no difference in both of them in react. I have raised an issue on GitHub regarding the same and this is what they have to say about it:
I think that at the time this decision was made (~4 years ago?), onInput didn’t work consistently between browsers, and was confusing to people coming to the web from other platforms, as they would expect the “change” event to fire on every change. In case of React it is a bigger issue because if you fail to handle change soon enough, the controlled inputs never update, leading people to think React is broken. So the team went with calling it onChange.
In retrospect it might have been a better idea to polyfill onInput and keep its name rather than change the behavior of another event. But that ship has sailed a long time ago. We might revisit this decision in the future, but I would just encourage you to treat it as a quirk of React DOM (which you’ll get used to pretty quickly).
https://github.com/facebook/react/issues/9567
Also this article will provide more insight. As a workaround for default 'onChange' being missing, the article suggests listening to the 'onBlur' event.
https://www.peterbe.com/plog/onchange-in-reactjs
For anyone who stumbled over this issue looking for a way to listen for the actual, DOM-based change event, this is how I did it (written in TypeScript):
import { Component, createElement, InputHTMLAttributes } from 'react';
export interface CustomInputProps {
onChange?: (event: Event) => void;
onInput?: (event: Event) => void;
}
/**
* This component restores the 'onChange' and 'onInput' behavior of JavaScript.
*
* See:
* - https://reactjs.org/docs/dom-elements.html#onchange
* - https://github.com/facebook/react/issues/3964
* - https://github.com/facebook/react/issues/9657
* - https://github.com/facebook/react/issues/14857
*/
export class CustomInput extends Component<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'ref'> & CustomInputProps> {
private readonly registerCallbacks = (element: HTMLInputElement | null) => {
if (element) {
element.onchange = this.props.onChange ? this.props.onChange : null;
element.oninput = this.props.onInput ? this.props.onInput : null;
}
};
public render() {
return <input ref={this.registerCallbacks} {...this.props} onChange={undefined} onInput={undefined} />;
}
}
Please let me know if you see ways to improve this approach or encounter problems with it. Unlike blur, the change event is also triggered when the user presses enter and is only triggered if the value actually changed.
I'm still gaining experience with this CustomInput component. For example, checkboxes behave strangely. I either have to invert event.target.checked in the onChange handler while passing the value to the checkbox with checked or get rid of this inversion when passing the value to the checkbox with defaultChecked but this then breaks that several checkboxes representing the same state in different places on the page keep in sync. (In both cases, I didn't pass an onInput handler to the CustomInput for checkboxes.)
One difference seems to be that onChange is not fired when selecting and replacing a character with the same character, while onInput is.
See this sandbox: https://codesandbox.io/s/react-onchange-vs-oninput-coggf?file=/src/App.js
Type "A" in the field, then select all and type "B". This will trigger 4 events, 2 onChange and 2 onInput.
Now select all and type "B" again, this till trigger a new onInput event, but no onChange.
As you can see in various comments here, React treats onChange and onInput the same and so, rather than debate the merits of this decision. Here's the solution.
Use onBlur when you don't want to process the user's edits until they're done. :)
Recently I got a bug where onChange would not allow copy and paste in the input field on IE11. Whereas the onInput event would allow that behavior. I could not find any documentation that would describe this in the docs, but that does show there is a difference between the two (expected or not).
The difference is that the oninput event occurs immediately after the value of an element has changed, while onchange occurs when the element loses focus, after the content has been changed.

Backbone.js best practice for event handlers naming

Let's say I have a function in a view that triggers when some kind of state is changed.
What would be best to name it and why?
stateChange
stateChanged
onStateChange
onStateChanged
I personally prefer to use onEventName names keeping the native naming convention for DOM event handlers.
Like myElement.onclick = function() { /* ... */ } for click event.
So for myEvent I'm using a handler named onMyEvent.
And if I have event stateChange, then I'll use onStateChange handler.
But really this question is more specific for each team of developers and code-style conventions inside the team/company.
So the main goal in such kinds of questions is to keep the code style the same in all parts to ensure readability.
Therefore if you're working in a team, just keep sticky to the team's code writing conventions and if you're working alone on existing code, try to keep its code style (sure if that style is not obviously ugly).
UPDATE: Understanding.
What is the event? Roughly it's an action initiated outside or inside the program, in other words, something happens in the system, e.g. some state changes (the state of the keyboard, of the mouse, of I/O devices, etc.) doesn't matter how (the user clicked on mouse or some program sent the mouse click signal to the system).
Say the browser window is subscribed to get notifications about some events and the operating system sends them to it as soon as possible, we'll assume that at the same time when something happens. So if the user clicks his mouse when the browser window is active and the document has a focus, the browser says to the document to fire the click event. And here our onclick handler starting its invocation. In other words, the system says to us that now happens a change of some state. And we're handling this change and not handling a fact saying to us that the state has been changed.
Let's assume that our handler is named onClicked. Since the handler's name saying in past tense we can get a reasonable question: "When clicked, how long ago it happened? How many times it was clicked? Hmm, maybe it's too late to handle this action (or actions?) at all...". So this name tells us that something happened sometime in past.
In contrast when our handler is named onClick it's obvious that click event just fired and fired once and we were notified about it immediately. And we're going to handle the click event - the information saying to us that the state of the mouse changed right now (not mouse clicked, but the event of click).
So the names in the past tense are more appropriate for the cases when we need to check if some state has been changed or not. E.g. if the variable stores the state = 1 we can call the function isStateChanged(); which will compare the value in state variable with the real value at the current moment. And here the past tense is a good choice for naming.
onStateChanged because this function triggers whenever some kind of state is changed.
I Googled a few names and noted the number of results returned. You can get some indication of the relative popularity of the most common forms for event handlers:
stateChanged 168k
stateChange 81k [1]
handleStateChange 61k
onStateChange 59k
onStateChanged 12k
beforeStateChange 2k
[1] Results show stateChange used mostly as the name of an event, not a handler.
Using different event types gives a much stronger recommendation towards the onStateChange form:
change [2]
onChange 2000k
onChanged 85k
handleChange 36k
beforeChange 27k
afterChange 22k
click [2]
onClick 48000k
onClicked 58k
handleClick 50k
beforeClick 8k [3]
onDrag 100k
handleDrag 36k
beforeDrag 32k
afterDrag 4k
onDragged 5k
[2] Too many results unrelated to programming.
[3] Apparently certain Microsoft API's can anticipate when the user is going to click.
My bet is for stateChanged due:
stateChange looks like an order, and looks like it receives a param with the new state.
onStateChange and onStateChanged are more keys for storing the handlers not the name for the handler itself.
IMHO
I usually go for a 2 factor event name. As an app grows in size, you may have more than one object who's state changes or perhaps a controller that can broadcast change events for more than one object and would therefore want to be able to differentiate between then both in code and in your head:
Object1:event
Object2:event
As for which event name, I think it comes down to personal preference and consistency.
I think one should make a difference based on the actual moment when the action is happening. For me onStateChange means that it is currently changing and I can be notified about this technically speaking right before the change.
OnStateChanged means the action already happened and I am notified at the end of it.
So, in between onStateChange and onStateChanged there is an important intention difference.
First one says "prepare yourself for this change" while the second one says "it's already happened".
Edit: I got carried away by the intention and didn't realize the naming itself.
Why the on prefix? This is reserved for handlers. The handlers will do something related to (on) that event.
So I would go with stateChange and stateChanged.

Categories

Resources