# 📈 Passing data to view ### Navigation - [🏡 Native modules made easy with Expo](/gYH9xz-oR2ai0Yih8if50w) - [👶 First Steps](/ANE6NSUlTSimTIrN-gMsBw) - [👉 ⚙️ Native Module](/mAIt0ctDTvSL5xV4uE9nWQ) - [📈 Passing data to view](/_gWWp8uoQwGkqKcEyfk8Tg) - [📚 View Props](/96IjlLNDRvydILdkbfaA5A) - [🔥 View Events](/PQWXYmxLRCebmLfx3Fh_gg) - [🏞️ View Functions](/DcjStCFdT6euzWqnJqCL6w) - [👷‍♂️ Classes and Shared Objects](/__42gVw8RqiIgfSbVseIvw) - [📊 Views and shared object](/IgHyIAHQQPCbeBD74Ri4BA) --- ### Task 1 Export from the `LinearChartModule` view with an empty line chart inside. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartModule.kt` ```kotlin View(LinearChartView::class) { } ``` :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartView.kt` ```kotlin // ... class LinearChartView( context: Context, appContext: AppContext ) : ExpoView(context, appContext) { private val chartView = LineChart(context) init { chartView.applyDefaultSettings() addView(chartView, ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT )) } } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/LinearChartModule.swift` ```swift View(LinearChartView.self) { } ``` :open_file_folder: File `ios/LinearChartView.swift` ```swift import ExpoModulesCore import Charts class LinearChartView: ExpoView { let chartView = LineChartView(frame: .zero) public required init(appContext: AppContext? = nil) { super.init(appContext: appContext) chartView.applyDefaultSettings() addSubview(chartView) } } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/3f552d0bf7ecf507f9389cd35ac6c629bfb1edfb) --- ### Task 2 To represent chart data, we will create records: `DataEntry` and `LinearDataSeries`. The `DataEntry` record should include an `x` and `y` value, while the `LinearDataSeries` record should (for now) have a single property called `values` that contains a list of `DataEntry`. :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartModule.kt` ```kotlin data class DataEntry( @Field val x: Float, @Field val y: Float ) : Record class LinearDataSeries : Record { @Field val values: List<DataEntry> = emptyList() } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/LinearChartModule.swift` ```swift struct DataEntry : Record { @Field var x: Double @Field var y: Double } struct LinearDataSeries : Record { @Field var values: [DataEntry] } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/5a42c26323d61a44c7e0753704d789f1db709d18) --- ### Task 3 Export a prop called `data` that receives the `LinearDataSeries` class. After that, attach provided data to view using the `LineChart.applyNewData` function. :::spoiler result ![](https://i.imgur.com/PH57BpP.png) ::: :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartModule.kt` ```kotlin Prop("data") { view: LinearChartView, series: LinearDataSeries? -> if (series != null) { view.setSeries(series) } } ``` ```kotlin fun setSeries(series: LinearDataSeries) { val dataSet = LineDataSet( series.values.map { Entry(it.x, it.y) }, "label" ) dataSet.apply { applyDefaultSettings() } chartView.applyNewData(dataSet) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/LinearChartModule.swift` ```swift Prop("data") { (view: LinearChartView, series: LinearDataSeries?) in if let series = series { view.setSeries(series) } } ``` ```swift func setSeries(_ series: LinearDataSeries) { let dataSet = LineChartDataSet( entries: series.values.map { ChartDataEntry(x: $0.x, y: $0.y) }, label: "label" ) dataSet.applyDefaultSettings() chartView.applyNewData(dataSet: dataSet) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/d273cb05cfaa792cc99be9c791642d2f10ac3c4e) --- ### Task 4 Extend the existing `LinearDataSeries` class to contain fields: - `label` - `lineWidth` - `textSize` :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartModule.kt` ```kotlin class LinearDataSeries : Record { @Field @Required val values: List<DataEntry> = emptyList() @Field @Required val label: String = "" @Field val lineWidth: Float = 5f @Field val textSize: Float = 10f } ``` ```kotlin fun setSeries(series: LinearDataSeries) { val dataSet = LineDataSet( series.values.map { Entry(it.x, it.y) }, series.label ) dataSet.apply { applyDefaultSettings() valueTextSize = series.textSize lineWidth = series.lineWidth } chartView.applyNewData(dataSet) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/LinearChartModule.swift` ```swift struct LinearDataSeries : Record { @Field var values: [DataEntry] @Field var label: String @Field var lineWidth = 5.0 @Field var textSize = 10.0 } ``` ```swift func setSeries(_ series: LinearDataSeries) { let dataSet = LineChartDataSet( entries: series.values.map { ChartDataEntry(x: $0.x, y: $0.y) }, label: "label" ) dataSet.applyDefaultSettings() dataSet.valueFont = dataSet.valueFont.withSize(series.textSize) // <- dataSet.lineWidth = series.lineWidth // <- chartView.applyNewData(dataSet: dataSet) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/25a02b69d06c79ee9fbf6e79a88051c6892293c8) --- ### Task 5 Create an enum representing a chart mode and integrate it with the `LinearDataSeries` class. Chart mode is an enum provided by the `MPAndroidChart`/`Chart` library. You should write a wrapper that operates on integers and can be converted to library representation. TypeScript representation of the `DataMode`: ```typescript export enum DataMode { LINEAR = 0, STEPPED = 1, CUBIC_BEZIER = 2, HORIZONTAL_BEZIER = 3, } ``` :::spoiler :robot_face: Android :open_file_folder: File `android/src/main/java/expo/modules/workshopscharts/LinearChartModule.kt` ```kotlin enum class DataMode(val value: Int) : Enumerable { LINEAR(0), STEPPED(1), CUBIC_BEZIER(2), HORIZONTAL_BEZIER(3); fun toLineDataSetMode(): Mode { return when (this) { LINEAR -> Mode.LINEAR STEPPED -> Mode.STEPPED CUBIC_BEZIER -> Mode.CUBIC_BEZIER HORIZONTAL_BEZIER -> Mode.HORIZONTAL_BEZIER } } } ``` ```kotlin class LinearDataSeries : Record { // ... @Field val mode: DataMode = DataMode.LINEAR } ``` ```kotlin fun setSeries(series: LinearDataSeries) { val dataSet = LineDataSet( series.values.map { Entry(it.x, it.y) }, series.label ) dataSet.apply { applyDefaultSettings() mode = series.mode.toLineDataSetMode() // <- valueTextSize = series.textSize lineWidth = series.lineWidth } chartView.applyNewData(dataSet) } ``` ::: :::spoiler :apple: iOS :open_file_folder: File `ios/LinearChartModule.swift` ```swift enum DataMode : Int, Enumerable { case LINEAR = 0, STEPPED, CUBIC_BEZIER, HORIZONTAL_BEZIER func toLineDataSetMode() -> LineChartDataSet.Mode { switch self { case .LINEAR: return .linear case .CUBIC_BEZIER: return .cubicBezier case .HORIZONTAL_BEZIER: return .horizontalBezier case .STEPPED: return .stepped } } } ``` ```swift struct LinearDataSeries : Record { // ... @Field var mode: DataMode = DataMode.LINEAR } ``` ```swift func setSeries(_ series: LinearDataSeries) { let dataSet = LineChartDataSet( entries: series.values.map { ChartDataEntry(x: $0.x, y: $0.y) }, label: "label" ) dataSet.applyDefaultSettings() dataSet.mode = series.mode.toLineDataSetMode() // <- dataSet.valueFont = dataSet.valueFont.withSize(series.textSize) dataSet.lineWidth = series.lineWidth chartView.applyNewData(dataSet: dataSet) } ``` ::: <br /> 📝 Full changelog: [open GitHub Commit](https://github.com/software-mansion-labs/appjs-2023-workshop-expo-modules/commit/96a7f56cea2addb762158f3ac46dfc088dbfdbd7) --- ### [📚 View Props](/96IjlLNDRvydILdkbfaA5A)