I am trying to simply bind a click event to all instances of a class using the .all method in YUI. For some reason it simply doesn't work. Here is the code:
YUI().use('io', 'json-parse', 'handlebars', 'node', 'event', function(Y) {
Y.all(".edit-user-button").on("click", function() {
alert("Click worked");
});
});
As you can see, I've imported the event and node modules but nothing happens when I click the buttons with that class edit-user-button.
EDIT: I am generating the elements with the class edit-user-button dynamically using Handlebars. This would otherwise work if the class already existed in the DOM but it is failing because it is dynamically loading.
Give it a try letting the container delegate the event to your buttons.
Y.one(".container").delegate('click', function(){
alert("Click worked");
}, ".edit-user-button")
More about this: http://yuilibrary.com/yui/docs/event/delegation.html
Hope this helps!
The reason may be that the elements with class 'edit-user-button' are created dynamically (o the class itself is added dynamically) and are not in the DOM yet when your code that sets the event handler runs.
This can be solved using a technique called Event Delegation
Using the YUI library you can apply that technique using the delegate method:
Y.one(".someContainer").delegate('click', function(){
alert("Click worked");
}, ".edit-user-button")
Info specific to YUI event delegation here.
Related
I've read questions like Access EventEmitter Service inside of CustomHttp
where the user uses EventEmitter in his service, but he was suggested in this comment
not to use it and to use instead Observables directly in his services.
I also read this
question
where the solution suggests to pass the EventEmitter to the child and subscribe to it.
My question then is: Should I, or should I not subscribe manually to an EventEmitter? How should I use it?
TL;DR:
No, don't subscribe manually to them, don't use them in services. Use them as is shown in the documentation only to emit events in components. Don't defeat angular's abstraction.
Answer:
No, you should not subscribe manually to it.
EventEmitter is an angular2 abstraction and its only purpose is to emit events in components. Quoting a comment from Rob Wormald
[...] EventEmitter is really an Angular abstraction, and should be used pretty much only for emitting custom Events in components. Otherwise, just use Rx as if it was any other library.
This is stated really clear in EventEmitter's documentation.
Use by directives and components to emit custom Events.
What's wrong about using it?
Angular2 will never guarantee us that EventEmitter will continue being an Observable. So that means refactoring our code if it changes. The only API we must access is its emit() method. We should never subscribe manually to an EventEmitter.
All the stated above is more clear in this Ward Bell's comment (recommended to read the article, and the answer to that comment). Quoting for reference
Do NOT count on EventEmitter continuing to be an Observable!
Do NOT count on those Observable operators being there in the future!
These will be deprecated soon and probably removed before release.
Use EventEmitter only for event binding between a child and parent component. Do not subscribe to it. Do not call any of those methods. Only call eve.emit()
His comment is in line with Rob's comment long time ago.
So, how to use it properly?
Simply use it to emit events from your component. Take a look a the following example.
#Component({
selector : 'child',
template : `
<button (click)="sendNotification()">Notify my parent!</button>
`
})
class Child {
#Output() notifyParent: EventEmitter<any> = new EventEmitter();
sendNotification() {
this.notifyParent.emit('Some value to send to the parent');
}
}
#Component({
selector : 'parent',
template : `
<child (notifyParent)="getNotification($event)"></child>
`
})
class Parent {
getNotification(evt) {
// Do something with the notification (evt) sent by the child!
}
}
How not to use it?
class MyService {
#Output() myServiceEvent : EventEmitter<any> = new EventEmitter();
}
Stop right there... you're already wrong...
Hopefully these two simple examples will clarify EventEmitter's proper usage.
Yes, go ahead and use it.
EventEmitter is a public, documented type in the final Angular Core API. Whether or not it is based on Observable is irrelevant; if its documented emit and subscribe methods suit what you need, then go ahead and use it.
As also stated in the docs:
Uses Rx.Observable but provides an adapter to make it work as specified here: https://github.com/jhusain/observable-spec
Once a reference implementation of the spec is available, switch to it.
So they wanted an Observable like object that behaved in a certain way, they implemented it, and made it public. If it were merely an internal Angular abstraction that shouldn't be used, they wouldn't have made it public.
There are plenty of times when it's useful to have an emitter which sends events of a specific type. If that's your use case, go for it. If/when a reference implementation of the spec they link to is available, it should be a drop-in replacement, just as with any other polyfill.
Just be sure that the generator you pass to the subscribe() function follows the linked spec. The returned object is guaranteed to have an unsubscribe method which should be called to free any references to the generator (this is currently an RxJs Subscription object but that is indeed an implementation detail which should not be depended on).
export class MyServiceEvent {
message: string;
eventId: number;
}
export class MyService {
public onChange: EventEmitter<MyServiceEvent> = new EventEmitter<MyServiceEvent>();
public doSomething(message: string) {
// do something, then...
this.onChange.emit({message: message, eventId: 42});
}
}
export class MyConsumer {
private _serviceSubscription;
constructor(private service: MyService) {
this._serviceSubscription = this.service.onChange.subscribe({
next: (event: MyServiceEvent) => {
console.log(`Received message #${event.eventId}: ${event.message}`);
}
})
}
public consume() {
// do some stuff, then later...
this.cleanup();
}
private cleanup() {
this._serviceSubscription.unsubscribe();
}
}
All of the strongly-worded doom and gloom predictions seem to stem from a single Stack Overflow comment from a single developer on a pre-release version of Angular 2.
When you want to have cross component interaction, then you need to know what are #Input , #Output , EventEmitter and Subjects.
If the relation between components is parent- child or vice versa we use #input & #output with event emitter..
#output emits an event and you need to emit using event emitter.
If it's not parent child relationship.. then you have to use subjects or through a common service.
When you want component interaction, then you need to know what are #Input , #Output , EventEmitter and Subjects.
If the relation between components is parent- child or vice versa we use #input & #output with event emitter..
#output emits an event and you need to emit using event emitter.
If it's not parent child relationship.. then you have to use subjects or through a common service
There is no: nono and no: yesyes.
The truth is in the middle
And no reasons to be scared because of the next version of Angular.
From a logical point of view, if You have a Component and You want to inform other components that something happens, an event should be fired and this can be done in whatever way You (developer) think it should be done. I don't see the reason why to not use it and i don't see the reason why to use it at all costs. Also the EventEmitter name suggests to me an event happening. I usually use it for important events happening in the Component. I create the Service but create the Service file inside the Component Folder. So my Service file becomes a sort of Event Manager or an Event Interface, so I can figure out at glance to which event I can subscribe on the current component.
I know..Maybe I'm a bit an old fashioned developer.
But this is not a part of Event Driven development pattern, this is part of the software architecture decisions of Your particular project.
Some other guys may think that use Observables directly is cool. In that case go ahead with Observables directly.
You're not a serial killer doing this. Unless you're a psychopath developer, So far the Program works, do it.
From a pure implementation perspective, since emit and subscribe are part of the public interface of EventEmitter, they can be used for implementation.
For angular there was no compulsion to inherit from behaviour if it didn't want it to, Behaviour could have been a private member in EventEmitter class, something like,
public class EventEmitter{
private _behaviour=new Subject<void>();
private _behaviour$=this._behaviour.asObservable();
......
public emit(){
_behaviour.emit();
}
....
}
If it inherits from Behvaiour but doesn't behave like one, then it is violation of liskov's susbstitution principle.
I want to use the RunOnUiThread for Update the UI (Chart and Label) with UI Thread by Timer. I am using the ContentPage. How can I use the Add the Activity class for RunOnUiThread on Content Page ? It's not supported.
I'd like to do the following:
RunOnUiThread(() => { tvTimer.Text = Convert.ToString(CountSeconds );});
Currently I am using the
Device.BeginInvokeOnMainThread(async () => });
for update the UI but UI is stucking or not updating properly like shows count down timer per seconds.
Please help me out
The reason I think it is happening is that because you are probably doing some minor mistake and from the code that I see I cannot make that out so I will give a reference sort of thing for you to take a look on :
Define a method to be executed on the main thread:
private async void MethodOnUIThread()
{
await **something**;
//Probably your timer code
//This method does not necessarily have to be async.
}
Run the method on Main thread something like this :
Device.BeginInvokeOnMainThread(MethodOnUIThread);
Revert in case of queries or if you do not understand something
I'm not very experienced with this topic so forgive me if this isn't very clear.
I've created a Portable Class Library that has an ObservableCollection of Sections, and each secion has an ObservableCollection of Items.
Both of these collections are bound to the UI of separate Win8 and WP8 apps.
I'm trying to figure out the correct way to populate these collections correctly so that the UI gets updated from the PCL class.
If the class was inside the win8 project I know I could do something like Dispatcher.BeginInvoke, but this doesn't translate to the PCL, nor would I be able to reuse that in the WP8 project.
In this thread (Portable class library equivalent of Dispatcher.Invoke or Dispatcher.RunAsync) I discovered the SynchroniationContext class.
I passed in a reference to the main app's SynchroniationContext, and when I populate the sections I can do so because it's only the one object being updated:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
UpdateSections(sections);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post(UpdateSections, sections);
}
However, when I try to do the same thing with articles, I have to have a reference to both the section AND the article, but the Post method only allows me to pass in a single object.
I attempted to use a lambda expression:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
section.Items.Add(item);
}, null);
}
but I'm guessing this is not correct as I'm getting an error about being "marshalled for a different thread".
So where am I going wrong here? how can I update both collections correctly from the PCL so that both apps can also update their UI?
many thanks!
Hard to say without seeing the rest of the code but I doubt is has anything to do with Portable Class Libraries. It would be good to see the details about the exception (type, message and stack trace).
The way you call Post() with more than argument looks correct. What happens if you remove the if check and simply always go through SynchronizationContext.Post()?
BTW: I don't explicitly pass in the SynchronizationContext. I assume that the ViewModel is created on the UI Thread. This allows me to capture it like this:
public class MyViewModel
{
private SynchronizationContext _context = SynchronizationContext.Current;
}
I would recommend that at least in your ViewModels, all publicly observable state changes (ie property change notifications and modifications to ObservableCollections) happen on the UI thread. I’d recommend doing the same thing with your model state changes, but it might make sense to let them make changes on different threads and marshal those changes to the UI thread in your ViewModels.
To do this, of course, you need to be able to switch to the UI thread in portable code. If SynchronizationContext isn’t working for you, then just create your own abstraction for the dispatcher (ie IRunOnUIThread).
The reason you were getting the "marshalled on a different thread" error is that you weren't passing the item to add to the list as the "state" object on the Post(action, state) method.
Your code should look like this:
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the CollectionChanged event on the current thread
section.Items.Add(item);
}
else
{
// Post the CollectionChanged event on the creator thread
_synchronizationContext.Post((e) =>
{
var item = (YourItemnType) e;
section.Items.Add(item);
}, item);
}
If you make that change, your code will work fine from a PCL.
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
I have an application that has a class named: UploadItem. The application creates uploading tasks based on information it has, for example, an upload needs to be created to upload a file to sitex.com with this the application creates a new UploadItem and adds that to an ObservableCollection, the collection is bound to a listview.
Now comes the part that I cannot solve.. I decided to change the structure so that people can create their own plugins that can upload a file, the problem lies with the fact that the UploadItem class has properties such as:
string _PercentagedDone;
public string PercentageDone
{
get { return _PercentagedDone; }
set { _PercentagedDone = value + "%"; NotifyPropertyChanged("PercentageDone"); }
}
But the plugin controls on how a file is uploaded, so how would the plugin edit the PercentageDone property that is located in the UploadItem class? If there is no way to do such a thing, then is there another way to achieve the same, i.e. showing the progress on the main GUI?
You'll want to define an interface for the plugins. Something like:
public interface IUploadPlugin
{
Task<bool> Upload(IEnumerable<Stream> files);
int Progress { get; }
}
The plugins then need to implement this interface and export themselves:
[Export(typeof(IUploadPlugin))]
public class MyUploader : IUploadPlugin, INotifyPropertyChanged
{
// ...
}
Notice that this plugin implements INotifyPropertyChanged. This is an easy way to handle updating the progress. Fire PropertyChanged on the Progress property and then databind your ProgressBar control in the main view to this property. Make sure that you fire PropertyChanged on the UI thread.
Another option would be to fire a custom event when the property changes. You could handle this event in the main view logic and update the progress.
Notice that I'm using Task for the return. This allows the caller to wait until the upload task finishes. You could use a callback instead, but with the CTP of the next version of .NET, using Task<> will allow you to use the await keyword for your async programming. Check it out here and here.