diff --git a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift index 163909cb..19348070 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift @@ -23,6 +23,8 @@ import Foundation public var analyticsData: JSONValueDictionary? public var fieldValue: String? + public func formFieldValue() -> AnyHashable? { return fieldValue } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index b9475938..a671726c 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -174,6 +174,10 @@ open class Carousel: View { pageIndex = carouselModel.index pagingView?.currentIndex = carouselModel.index collectionView.reloadData() + if let selectedIndex = carouselModel.selectedIndex { + let adjustedIndex = loop ? selectedIndex + 2 : selectedIndex + collectionView.selectItem(at: IndexPath(row: adjustedIndex, section: 0), animated: false, scrollPosition: []) + } } //-------------------------------------------------- @@ -392,16 +396,25 @@ extension Carousel: UICollectionViewDataSource { } extension Carousel: UICollectionViewDelegate { + public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { + guard let cell = collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol else { return false } + return cell.shouldSelect(at: indexPath, delegateObject: delegateObject, additionalData: nil) + } + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let cell = collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol else { - return + // Set the selection in the model + if let model = model as? CarouselModel { + // Adjust for looping + var adjustedIndex = loop ? indexPath.row - 2 : indexPath.row + if adjustedIndex < 0 { + adjustedIndex = adjustedIndex + numberOfPages + } + model.selectedIndex = adjustedIndex } - cell.didSelectCell(at: indexPath, delegateObject: delegateObject, additionalData: nil) - //Check for selectable carousel item - guard let carouselModel = model as? CarouselModel, let selectedCarouselItem = carouselModel.molecules[indexPath.row] as? CarouselItemModel, cell.shouldSelect(at: indexPath, delegateObject: delegateObject, additionalData: nil) else { - return + if let cell = collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol { + cell.didSelectCell(at: indexPath, delegateObject: delegateObject, additionalData: nil) } - carouselModel.selectedIndex = selectedCarouselItem.fieldValue ?? String(indexPath.row) + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } } @@ -423,6 +436,7 @@ extension Carousel: UIScrollViewDelegate { if !animated { scrollViewDidEndScrollingAnimation(collectionView) } + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } /// Adjusts the current contentOffset if we are going onto buffer cells while looping to help with the endless scrolling appearance. diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index caa9f844..5bf0728c 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -34,28 +34,29 @@ import UIKit public var leftPadding: CGFloat? public var rightPadding: CGFloat? public var accessibilityText: String? - public var selectedIndex: String? public var baseValue: AnyHashable? public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName + public var selectable = false + public var selectedIndex: Int? + public init(molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]) { self.molecules = molecules } public func formFieldValue() -> AnyHashable? { - var carouselItemFieldValue: AnyHashable? - guard let visibleCarouselItem = molecules[index] as? CarouselItemModel else { - return nil + guard selectable else { + // Use visible item value, else index + if let fieldValue = molecules[index].formFieldValue() { + return fieldValue + } + return index } - if selectedIndex != nil { - //For selectableCarouselItem - carouselItemFieldValue = selectedIndex - } else { - //For carouselItem - carouselItemFieldValue = (visibleCarouselItem.fieldValue != nil) ? visibleCarouselItem.fieldValue : String(index) - } - return carouselItemFieldValue + // Use selected item value, else index + guard let selectedIndex = selectedIndex else { return nil } + guard let fieldValue = molecules[selectedIndex].formFieldValue() else { return selectedIndex } + return fieldValue } //-------------------------------------------------- @@ -81,6 +82,8 @@ import UIKit case accessibilityText case groupName case fieldKey + case selectable + case selectedIndex } //-------------------------------------------------- @@ -91,6 +94,8 @@ import UIKit let typeContainer = try decoder.container(keyedBy: CodingKeys.self) molecules = try typeContainer.decodeModels(codingKey: .molecules) index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0 + selectable = try typeContainer.decodeIfPresent(Bool.self, forKey: .selectable) ?? false + selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border) @@ -134,5 +139,8 @@ import UIKit try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encode(groupName, forKey: .groupName) + try container.encode(index, forKey: .index) + try container.encode(selectable, forKey: .selectable) + try container.encode(selectedIndex, forKey: .selectedIndex) } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift index c2ade02d..2ed2ca5a 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift @@ -11,11 +11,14 @@ import Foundation public protocol CarouselItemModelProtocol: ContainerModelProtocol { var analyticsData: JSONValueDictionary? { get set } + func formFieldValue() -> AnyHashable? } + public extension CarouselItemModelProtocol { var analyticsData: JSONValueDictionary? { get { return nil } set { analyticsData = newValue } } + func formFieldValue() -> AnyHashable? { return nil } } diff --git a/MVMCoreUI/Atomic/Templates/CollectionTemplateItemProtocol.swift b/MVMCoreUI/Atomic/Templates/CollectionTemplateItemProtocol.swift index 98c9754e..4e9ae26d 100644 --- a/MVMCoreUI/Atomic/Templates/CollectionTemplateItemProtocol.swift +++ b/MVMCoreUI/Atomic/Templates/CollectionTemplateItemProtocol.swift @@ -22,7 +22,6 @@ public protocol CollectionTemplateItemProtocol: UICollectionViewCell { /// Handle the selection of cell func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool - } // Default implementation does nothing @@ -34,5 +33,4 @@ extension CollectionTemplateItemProtocol { public func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool { return false } - } diff --git a/MVMCoreUI/BaseClasses/CollectionViewCell.swift b/MVMCoreUI/BaseClasses/CollectionViewCell.swift index aff6dffb..cfbe4ac7 100644 --- a/MVMCoreUI/BaseClasses/CollectionViewCell.swift +++ b/MVMCoreUI/BaseClasses/CollectionViewCell.swift @@ -116,11 +116,15 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo // MARK: - Override - open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - guard let action = model?.action else { return } - Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData) + open func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool { + if let action = model?.action { + Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData) + } + return false } + open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {} + // Column logic, set width. override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes) @@ -132,9 +136,4 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo autoLayoutAttributes.frame = newFrame return autoLayoutAttributes } - - // Set default to false - open func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) -> Bool { - return false - } }