Developer

Customizing the Judo View

Overriding Properties

Bind values for properties to your Judo UI components when embedding them into your app with JudoView at runtime.


Usage

Judo allows you to define properties on your components, and then to bind them to arbitrary layers (Text, Images, etc.) within the component.

When you use JudoView to emebed Judo components at runtime, you can pass in custom values for those properties.

This is done with the property(_:_:) modifier, which allows you to provide values for given properties by name.

For example, for the given component with the following property added:

Component property setup

You would use the following SwiftUI to provide a custom value for the property:

struct MyComponent: View {
    var body: some View {
        // Main.judo
        JudoView("Main")
            .component("Component1")
            .property("counter", 3)
    }
}

Simplify syntax by passing multiple property values at once

You can pass multiple property values at once by using the properties(_:) modifier, which takes a dictionary of property names and values.


Supported property types

Alongside Swift's String (text), Boolean, and Numeric types, Judo also supports image values.

In addition to the above value types, Judo also supports passing in custom SwiftUI views as values in order to enable embedding custom views within your Judo UI. See Custom Views for more information.

Image value properties

Judo properties support SwiftUI Image values. This allows you to pass in and embed arbitrary images into your Judo components as SwiftUI value types, that can then be bound to a Judo image layer within a component.

Create an Image property on your Judo component, and then pass in the image using the property(_:_:) modifier.

For example, for the given component with a property named ThumbnailPhoto:

Image property setup

You would use the following SwiftUI to provide a custom image value for the property:

struct MyComponent: View {
    var body: some View {
        // Main.judo
        JudoView("Main")
            .component("Component1")
            .property("ThumbnailPhoto", thumbnailPhoto)
    }

    var thumbnailPhoto: Image {
        // In this example, we obtain an image entitled `my-image`
        // from the asset bundle, but you can use any SwiftUI Image
        // value here.
        Image("my-image")
    }
}

Remote images

If you have a URL of a remote image instead of a local one, Judo also supports downloading and displaying images over the network, using the AsyncImage layer in lieu of the Image layer.

Your Judo component should instead accept a text property of the image URL rather than an Image value, and then you can pass in the URL as a string value.

Your component can then bind that text property to the URL value of of the AsyncImage.


Two-way bindings

Judo includes ineractive controls (Toggle, Picker, Text Field, etc.) and mutating actions (eg., using Increment/Decrement/Set Value actions on a Button). These can be be used to update state in your app.

This is supported by passing a SwiftUI Binding for a property in lieu of the value itself, which allows you to enable two-way binding of of a value in your app's state.

In this example, we'll define a custom component in Judo called MealItem for a shopping cart:

Bindings

Then we'll bind it to state in a SwiftUI view like this:

struct MealItem: View {
    var title: String
    val imageThumbnail: Image

    /// This value will be updated by the Judo meal cart item increment/decrement controls through a binding.
    @State var quantity: Int

    var body: some View {
        // Main.judo
        JudoView("Main")
            .component("Meal")
            .property("title", title)
            .property("image", imageThumbnail)
            // notice the $, which is asking Swift to project the 
            // @Binding property wrapper, which Judo can then use to
            // write value changes back.
            .property("quantity", $quantity)
    }
}

Organize your property identifiers with strong typing

property(_:_:)'s first parameter is actually a PropertyName value, which while remaining easily representable by default by a string, allows you to explicitly define your property identifiers in a more type-safe way.

This allows for a convenient way to organize your property identifiers.

extension PropertyName {
    static let counter = PropertyName("counter")
}

// and then, within your SwiftUI view:
JudoView("Main")
    .component("Component1")
    .property(.counter, 3)
Previous
Rendering Components