Access to XAML controls in a React Native for Windows application (Part 2)
Published: 2023-10-31 10:08:23

---
title: Access to XAML controls in a React Native for Windows application (Part 2)
published: true
date: 2022-05-20 13:29:38 UTC
tags: 
canonical_url: 
---

[In the previous blog post](https://dev.to/qmatteoq/access-to-xaml-controls-in-a-react-native-for-windows-application-5c3p-temp-slug-8151335) I showed one approach to manage a scenario that can't be done in React Native for Windows out of the box: getting access to the native XAML controls behind the JSX ones, so that you can support scenarios like showing a flyout near another control.

Thanks to the feedback from [Steven Moyes](https://twitter.com/moyessa) and [Alexander Sklar](https://twitter.com/alexsklar) from the React Native for Windows PG, I've found out that there's a better way to achieve the same goal. Alexander is the main maintainer of an open-source library, published by Microsoft, called [react-native-xaml](https://github.com/microsoft/react-native-xaml), which enables you to bring any XAML control into your React Native for Windows applications. The only caveat is that such a UI won't be any more really cross-platform, since these controls can't be rendered on Android, iOS or macOS. However, the same limitation applies to the approach we have seen in the previous post, since `Flyout` is a control which is available only for Windows.

Thanks to react-native-xaml, you can easily build a component like the following one:

 

```
import React from 'react';
import { DatePicker } from 'react-native-xaml';
import { View } from 'react-native';

const MyXamlComponent = () => {

    return (
    <View>
        <DatePicker dayVisible={false} onSelectedDateChanged={(args) => console.log(args.nativeEvent.args.newDate) } />
      </View>
    );
    
}

export default MyXamlComponent;

```

 

We are importing the `DatePicker` control from the react-native-xaml library, which is mapped to the native [DatePicker](https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.datepicker?view=winui-3.0) control in WinUI. Thanks to the library, we have also access to the same properties and events we have in XAML, but exposed in camel case to follow the JavaScript naming conventions. In the previous snippet, you can see we're setting the `dayVisible` property to hide the day from the selection and we're subscribing to the `onSelectedDateChanged` event to get notified any time the user selects a date. We even have access to the event arguments raised by the event, using the `nativeEvent.args` property. Now we have a fully fledged `DatePicker` control available in our application, without having to write a custom native module:

 

![datepicker.png](https://techcommunity.microsoft.com/t5/image/serverpage/image-id/373609iA03F2C5A88E58828/image-size/large?v=v2&px=999 "datepicker.png")

Is it possible to use react-native-xaml to implement the scenario we have seen yesterday with the `Flyout` control? Yes!

 

### Connecting a flyout to an existing control

Thanks to react-native-xaml, we can import true XAML controls in our application, which means that they behave in the same way they would do in a native XAML application. As such, we can simply attach a flyout in the same way we would do in a XAML page. Let's see the code:

 

```
import React, {useState} from 'react';
import { TextBox, MenuFlyout, MenuFlyoutItem } from 'react-native-xaml';
import { View } from 'react-native';

const XamlNotificationComponent = () => {

    return (
    <View>
      <TextBox text="this is a textbox with a menuFlyout">
        <MenuFlyout>
          <MenuFlyoutItem text="option 1" onClick={() => { alert('clicked 1'); }} />
          <MenuFlyoutItem text="option 2" onClick={() => { alert("clicked 2");}} />
        </MenuFlyout>
        </TextBox>
        
      </View>
    );
}

export default XamlNotificationComponent;

```

First, we import a few controls from the react-native-xaml library: `TextBox`, `MenuFlyout` and `MenuFlyoutItem`. Then, exactly like we would do in XAML, we define a new `MenuFlyout` control, and we set it as children of the `TextBox` control. This way, we'll anchor the flyout to the `TextBox`, so that it will be displayed close to it. Like in XAML, we can subscribe to the onClick event to trigger an action when an item is selected. In this case, we just display a popup with a message.

We have created the flyout, now we must make it visible. Let's expand the code to add a Button to our component, which will trigger the flyout once it's clicked:

 

```
import React, {useState} from 'react';
import { TextBox, MenuFlyout, MenuFlyoutItem, Button } from 'react-native-xaml';
import { View } from 'react-native';

const XamlNotificationComponent = () => {
    [isOpen, setIsOpen] = useState(false);

    return (
    <View>
      <TextBox text="this is a textbox with a menuFlyout">
        <MenuFlyout isOpen={isOpen} onClosed={() => { setIsOpen(false); }}>
          <MenuFlyoutItem text="option 1" onClick={() => { alert('clicked 1'); }} />
          <MenuFlyoutItem text="option 2" onClick={() => { alert("clicked 2");}}/>
        </MenuFlyout>
        </TextBox>
        <Button content="Show flyout" onClick={(a) => { setIsOpen(true); }} />

      </View>
    );
    
}

export default XamlNotificationComponent;

```

Compared to the first snippet, we have made the following changes:

- Using the `useState()` React hook, we have created a new property to store in the state called `isOpen`. We're going to use it to store the information if the flyout is open or closed.
- We have connected the `isOpen` property in the state to the `isOpen` property of the `MenuFlyout` control. This way, we can keep them coordinated and, when the state changes, also the flyout will be displayed or hidden automatically.
- Flyouts leverage a light dismiss UI. They can be closed simply by clicking outside the flyout. As such, since we need to make sure that we keep the state coordinated with the status of the control, we subscribe to the `onClosed` event, and we set the `isOpen` property in the state to `false`.
- We have added a `Button` control and we have subscribed to the `onClick` event. When it's clicked, we're going to set the `isOpen` property in the state to `true`, which will make the flyout appear.

That's it! Now, when you click on the button, you will see the flyout being displayed on top of the `TextBox` control, in the same way we did in the previous blog post, but without needing to create a custom native module:

![flyout.png](https://techcommunity.microsoft.com/t5/image/serverpage/image-id/373610i4F17AD1D7471CCFD/image-size/large?v=v2&px=999 "flyout.png")

 

 

### Displaying a flyout in a specific area of the application

In the previous blog post, we used the reference approach supported by React Native to pass the JSX control to our native module, so that we could retrieve the underneath XAML control and show the flyout close to it. The reference approach can also be helpful in case you want to use react-native-xaml to display a flyout in a specific area of the application. Let's see the code!

 

```
import React from 'react';
import { View} from 'react-native';
import { MenuFlyout, MenuFlyoutItem, Button } from 'react-native-xaml';

class XamlNotificationWithRefComponent extends React.Component {

    constructor(props) {
        super(props);
        this.myFlyout = React.createRef();
    }
      showNotification = () => {
          MenuFlyout.ShowAt(this.myFlyout, { point: { x: 120, y: 130}});
      };

      render() {
        return (
            <View>
                <MenuFlyout ref={this.myFlyout}>
                    <MenuFlyoutItem text='option 1' />
                    <MenuFlyoutItem text='option 2' />
                </MenuFlyout>
                <Button
                    content="Click me"
                    onClick={this.showNotification} />
            </View>
        );
    }
}

export default XamlNotificationWithRefComponent;

```

First, we create a `MenuFlyout` control in JSX, using the react-native-xaml library. However, this time, we are using the `React.createRef()` method we've learned in the previous post to store a reference to the control using the `myFlyout` variable. Once we have a reference, we can call the `ShowAt()` method exposed by the base `MenuFlyout` control, which requires two parameters:

- The `MenuFlyout` control we want to display. This is where we use the reference we have just acquired.
- The coordinates where we want to display it, using a `point` object.

Thanks to this code, we can display the flyout in any position we want, as in the following image:

 

![flyout-coordinates.png](https://techcommunity.microsoft.com/t5/image/serverpage/image-id/373612i35E7E95F411AAE69/image-size/large?v=v2&px=999 "flyout-coordinates.png")

 

### Wrapping up

react-native-xaml is an amazing library, which helps you to get the best of both worlds: the great developer experience offered by React Native and the powerful XAML controls offered by WinUI. If you want to see more examples of how to use it, I recommend checking the guide [you'll find in the GitHub repository](https://github.com/microsoft/react-native-xaml/blob/main/USAGE.md).

 

I've also updated [my sample](https://github.com/qmatteoq/InAppNotifications) to support the scenarios we've seen in this post.

 

Happy coding!