DEV Community

Akash Kava for Web Atoms

Posted on

How to write Xamarin.Forms events in TypeScript?

Events and Commands

Both events and commands can be written in one single pattern.


<XF.Button
    command={(e) => this.viewModel.save()}
    />

// OR

<XF.Button
    command={Bind.event((s, e) => this.viewModel.save())}
    />

Enter fullscreen mode Exit fullscreen mode

There are two ways you can create event handler, one is simply a lambda function that can accept single parameter. In this expression, you cannot access current control, which may be useful when you are inside a multiple items container such as ListView or CollectionView or even BindableLayout.

You could simply write a function, but sometimes you may need to access enclosing AtomControl and its data or viewModel property.

Multiple Items Control

<XF.CollectionView>
   <XF.CollectionView.itemTemplate>
      <XF.DataTemplate>
          <XF.Label>
             <XF.Label.gestureRecognizers>
                 <XF.TapGestureRecognizer
                      command={Bind.event((s, e) =>
                         this.viewModel.select(s.data) }
                      />
             </XF.Label.gestureRecognizers>
          </XF.Label>
      </XF.DataTemplate>
   </XF.CollectionView.itemTemplate>
</XF.CollectionView>
Enter fullscreen mode Exit fullscreen mode

Every item inside items container has an atom control associated with it, to access the data (BindingContext) associated with the control, we need to wrap lambda in Bind.event which gives us data property.

The syntax is similar to event handler syntax of Xamarin.Forms, with only difference being, sender is the AtomControl.

Data vs BindingContext

In order to improve speed and to keep JavaScript code isolated and consistent throughout different frameworks, we use data property instead of BindingContext as sometimes you may need to access more JavaScript properties such as viewModel/localViewModel etc.

Keeping bindings free from underlying platform also reduces amount of possible data transfer between both platforms and reduces possibility of memory leaks.

When you move your code to Web or other native platforms, BindingContext could be called some different name on different platforms.

Event Parameter

Event parameter object is serialized in JavaScript using WeakReference, you can call method and get/set property on it. Since it is weak reference, you cannot store it in JavaScript. You can only extract some information and you can store that information with you.

Dispatch Event

In order to keep event dispatch exactly same as in Html, we have added CustomEvent and dispatchEvent support for native elements of Xamarin.Forms.


export default class MyCustomControl extends AtomXFContentView { 

   ...

   // dispatch..
   this.element.dispatchEvent(new CustomEvent("customEvent", { detail: param }));

   ...
Enter fullscreen mode Exit fullscreen mode

Listen for event..


   <MyCustomControl
       eventCustomEvent={Bind.event((s, e) => this.viewModel.onEvent(e.detail))}
       />

Enter fullscreen mode Exit fullscreen mode

Even though such event does not exist in Xamarin.Forms element, you can still subscribe to it and listen for it, it works exactly similar to HTML events.

Event Execution

All events are fired under main UI thread, so it is recommended that do not do any long processing in event handler.

Async Event Handler

All event handlers are assumed to be async by default, so if you return a promise in your event handler, error will be caught and it will be displayed in console.

@Action() decorator

In order to display an alert for any exception, you can decorate your event handler with @Action() decorator.

   @Action({ validate: true })
   public async save() {
      ....
   }
Enter fullscreen mode Exit fullscreen mode

Validate

Setting validate true, will fire up all validations and action will be executed if only all validations pass through.

Success

If set to true, or a non empty string, an alert message box will be displayed after successful execution.

Memory Leaks

Since dealing with multiple runtimes can quickly introduce memory leaks, Web Atoms systematically disposes every event registered via TSX code. It is better if you register events only through TSX.

Otherwise, every event registration done in JavaScript returns a disposable, which you can add to your viewModel. View model has collection of disposables and it disposes every registered disposable when view model is disposed.

Top comments (0)