View Source LiveViewNative.Component (live_view_native v0.4.0-rc.0)

Define reusable LiveView Native function components with NEEx templates.

This module is used for the following

  • format specific render components
  • format specific functional components
  • format specific layouts

LiveView Native Components differ from Phoenix Components in that they make use of a two-argument function instead of a single argument function. For example, with a Phoenix Component that has a template named foo_bar.html.heex it would define foo_bar/1 as the rendering function for that template when embeded. LiveView Native Components would definee foo_bar/2 for foo_bar.swiftui.neex with the 1st argument still being assigns and the 2nd argument being interface map with information about the native client that is connecting.

For more information on template embedding see LiveViewNative.Renderer.embed_templates/2

Interface map

Each native client can optionally send along an interface map that has at least the following information:

  • "target" - the target device within the platform family. For example, ios, ipados, watchos are all targets for the SwiftUI platform. Each client library should have information on the valid targets
  • "version" - the version of your application. This is a value that you can control and pattern match on. The version will need to be set in the native client build.
  • "client_version" - the version of the client library that is connecting. The client will set this.

Summary

Functions

Uses LiveView Native Component in the current module

Embed the CSRF token for LiveView as a tag

The ~LVN sigil for writing HEEx templates inside source files.

Functions

__using__(opts)

(macro)

Uses LiveView Native Component in the current module

Options

Format-Specific Render Component

defmodule MyAppWeb.HomeLive.SwiftUI do
  use LiveViewNative.Component,
    format: :swiftui,
    as: :render
end

In this example :as is used and this will inject following:

embed_templates("swiftui/home_live*", root: nil, name: :render)

Assuming there is a swiftui/home_live.swiftui.neex this will be embeded in the render component as render/2.

Alternatively if you do not want to use templates but the in-line rendering you can declare your own render/2 functions

def render(assigns, %{"target" => "watchos"}) do
  ~LVN"""
  <Text>Hello, from WatchOS!</Text>
  """
end

def render(assigns, %{"target" => target}) when target in ~w{macos tvos} do
  ~LVN"""
  <Text>Hello, from <%= target %>!</Text>
  """
end

def render(assigns, _interface) do
  ~LVN"""
  <Text>Hello, from SwiftUI!</Text>
  """
end

Format-Specific Function Component

defmodule MyAppWeb.NativeComponent.SwiftUI do
  use LiveViewNative.Component,
    format: :swiftui
end

When using to write your own function components it is nearly identical to Phoenix.Component. You will use embed_templates/2 for template embedding and this will inject functions that take assigns and interface as arguments.

You can also define your own functions but you lose the 2 arity, or you can create it yourself.

def radio_button(assigns) do
  interface = LiveViewNative.Utils.get_interface(assigns)
  radio_button(assign, interface)
end

def radio_button(assigns, %{"target" => "watchos"}) do
  ~LVN"""
    ...
  """
end

Format-Specific Layouts

defmodule MyAppWeb.Layouts.SwiftUI do
  use LiveViewNative.Component,
    format: :swiftui

  import LiveViewNative.Component, only: [csrf_token: 1]

  embed_templates "layouts_swiftui/*"
end

Most times you will want to provide app and root templates. For stylesheet embedding refer to LiveViewNative.Stylesheet.Component

csrf_token(assigns)

Embed the CSRF token for LiveView as a tag

sigil_LVN(arg, modifiers)

(macro)

The ~LVN sigil for writing HEEx templates inside source files.

Using ~LVN is nearly identical to ~H in Phoenix.Component but deviates in various ways.

One common misconception is that LiveView Native templates are just HTML or XML. This is not true. Both HTML and XML have specifications that at times conflict with the needs of how LiveView Native client UI frameworks should be represented. Think of LiveView Native templates as a composable markup whose specification is currently under development. As we continue to expand the LiveView Native ecosystem this list will likely grow:

  • casing - ~LVN does not enforce downcasing of tag names so <Text> is a valid tag name

Special attributes

LVN tempalates support all of the HEEx special attributes in addition to LVN-specific special attributes:

:interface-

The :interface- atrribute allows you to match against a given interface value from the client. Similar to data- in HTML the name that is appended is the key within the deeply nested value to match against. For example :interface-target:

<Text :interface-target="mobile">This is a phone</Text>
<Text :interface-target="watch">This is a watch</Text>

The elements will conditionally render based upon a matching interface["target"] value. Internally this is converted to :if:

<Text :if={get_in(assigns, [:_interface, "mobile"])}>This is a phone</Text>
<Text :if={get_in(assigns, [:_interface, "watch"])}>This is a watch</Text>

This convenience is intended for UI where one-off changes are necessary for specific cases to avoid having to define an entirely new template.