Skip to content

Commit

Permalink
Merge pull request #53 from intuit/customCardStates
Browse files Browse the repository at this point in the history
Add custom card state
  • Loading branch information
bharathmurs authored Jun 20, 2018
2 parents 056a846 + 937f4f7 commit 8cac1e2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 14 deletions.
11 changes: 6 additions & 5 deletions CardParts/src/Classes/CardPartsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import UIKit
import RxSwift
import RxCocoa

public enum CardState {
case none
case loading
case empty
case hasData
public enum CardState: Hashable {
case none
case loading
case empty
case hasData
case custom(String)
}

class CardStateData {
Expand Down
20 changes: 13 additions & 7 deletions Example/CardParts/StateCardController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import RxCocoa

class StateCardController : CardPartsViewController {

let customStateKey = "myCustomState"

init() {
super.init(nibName: nil, bundle: nil)
startRandomHides()
Expand All @@ -33,20 +35,24 @@ class StateCardController : CardPartsViewController {

let textPart = CardPartTextView(type: .normal)
textPart.text = "Watch me change states!"

setupCardParts([textPart])

let spacerPart = CardPartSpacerView(height: 200)
let loadingCardPart = CardPartTextView(type: .normal)
loadingCardPart.text = "I am a loading state"

setupCardParts([textPart], forState: .empty)
setupCardParts([spacerPart], forState: .hasData)
let customCardPart = CardPartTextView(type: .normal)
customCardPart.text = "I am a custom state that you can make!"

setupCardParts([textPart], forState: .empty)
setupCardParts([loadingCardPart], forState: .loading)
setupCardParts([customCardPart], forState: .custom(customStateKey))
}

@objc func toggleHidden() {
if state == .empty {
state = .hasData
} else {
state = .loading
} else if state == .loading {
state = .custom(customStateKey)
} else if state == .custom(customStateKey) {
state = .empty
}
}
Expand Down
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -720,32 +720,48 @@ Add the above orientedView to any list of card parts or an existing stack view t
CardPartsViewController can optionally support the notion of card states, where a card can be in 3 different states: loading, empty, and hasData. For each state you can specify a unique set of card parts to display. Then when the CardPartsViewController state property is changed, the framework will automatically switch the card parts to display the card parts for that state. Typically you would bind the state property to a state property in your view model so that when the view model changes state the card parts are changed. A simple example:

```swift
public enum CardState {
case none
case loading
case empty
case hasData
case custom(String)
}

class TestCardController : CardPartsViewController {

var viewModel = TestViewModel()
var titlePart = CardPartTitleView(type: .titleOnly)
var textPart = CardPartTextView(type: .normal)
var loadingText = CardPartTextView(type: .normal)
var emptyText = CardPartTextView(type: .normal)
var customText = CardPartTextView(type: .normal)

override func viewDidLoad() {
super.viewDidLoad()

viewModel.title.asObservable().bind(to: titlePart.reactive.title).disposed(by: bag)
viewModel.text.asObservable().bind(to: textPart.reactive.text).disposed(by: bag)
viewModel.title.asObservable().bind(to: titlePart.rx.title).disposed(by: bag)
viewModel.text.asObservable().bind(to: textPart.rx.text).disposed(by: bag)

loadingText.text = "Loading..."
emptyText.text = "No data found."
customText.text = "I am some custom state"

viewModel.state.asObservable().bind(to: self.rx.state).disposed(by: bag)

setupCardParts([titlePart, textPart], forState: .hasData)
setupCardParts([titlePart, loadingText], forState: .loading)
setupCardParts([titlePart, emptyText], forState: .empty)
setupCardParts([titlePart, customText], forState: .custom("myCustomState"))
}
}
```

*Note: There is a `custom(String)` state which allows you to use more than our predefined set of states:*
```swift
.custom("myCustomState")
```

## Data Binding
Data binding is implemented using the RxSwift library (https://github.com/ReactiveX/RxSwift). View models should expose their data as bindable properties using the Variable class. In the example above the view model might look like this:
```swift
Expand Down

0 comments on commit 8cac1e2

Please sign in to comment.