How Pass Data from Button in Tableviewcell to View Controller

How pass data from button in TableViewCell to View Controller?

Function @IBAction func infoButtonAction(_ sender: Any) {} should be in the ProductListCell

When that button is tapped, connect with the ProductListVC by delegate or closure to get the selected product.

Update

Using delegate:
Update your ProductListCell

import UIKit
import SDWebImage
import Firebase

protocol ProductListCellDelegate: class {
func onTouchInfoButton(from cell: ProductListCell)
}

class ProductListCell: UITableViewCell {

@IBOutlet weak var productImage: UIImageView!
@IBOutlet weak var dispensaryName: UILabel!
@IBOutlet weak var productName: UILabel!
@IBOutlet weak var thcPercent: UILabel!
@IBOutlet weak var cbdPercent: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var categoryStrain: UILabel!

@IBOutlet weak var moreInfo: RoundButton!
weak var product: Product!
weak var delegate: ProductListCellDelegate?

func configure(withProduct product: ProductList) {
self.product = product
productName.text = "\(String(describing: product.brand)): \(String(describing: product.name))"
dispensaryName.text = product.dispensaryName
categoryLabel.text = product.category
productImage.sd_setImage(with: URL(string: product.imageUrl))
cbdPercent.text = product.cbd
thcPercent.text = product.thc
categoryStrain.text = product.strain
}

@IBAction func infoButtonAction(_ sender: Any) {
self.delegate?.onTouchInfoButton(from: self)
}
}

In your ProductListVC:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }

cell.configure(withProduct: productSetup[indexPath.row])

cell.delegate = self

return cell
}

extension ProductListVC: ProductListCellDelegate {
func onTouchInfoButton(from cell: ProductListCell) {
let selectedProduct = cell.product
// Do your stuff here
}
}

UPDATE

Because you use segue for navigation so let's create a variable to store your selected product in your ProductListVC

import UIKit
import Firebase
import FirebaseFirestore

class ProductListVC: UIViewController {

@IBOutlet weak var productListTableView: UITableView!

var productInventory: [ProductList] = []
var productSetup: [ProductList] = []
var selectedProduct: Product?

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}

override func viewDidLoad() {
super.viewDidLoad()

productListTableView.dataSource = self
productListTableView.delegate = self
searchBar.delegate = self

fetchProducts { (products) in
self.productSetup = products
self.productListTableView.reloadData()
}

}
func fetchProducts(_ completion: @escaping ([ProductList]) -> Void) {
let ref = Firestore.firestore().collection("products")
ref.addSnapshotListener { (snapshot, error) in
guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
return
}
completion(snapshot.documents.compactMap( {ProductList(dictionary: $0.data())} ))
}
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? MoreInforVC {
vc.product = self.selectedProduct
}
}
}

extension ProductListVC: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

return productSetup.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }

cell.configure(withProduct: productSetup[indexPath.row])

cell.delegate = self

return cell
}

}

extension ProductListController: ProductListCellDelegate {
func onTouchInfoButton(from cell: ProductListCell) {
self.selectedProduct = cell.product
self.performSegue(withIdentifier: "YourSegueIdentifier", sender: self)
}
}

Passing data from Table view cell using button delegate

The problem is you don't update you're global properties when selecting each of you're row,

If you pass data over cell delegate and pass you're cell through delegate, you can pass data from cell like:

    customViewController?.titlemovie = cell.movieTitle.text ?? ""
customViewController?.imagemovie = cell.movieImage.image
customViewController?.overview = cell.movieOverview.text ?? ""

of course it would be better to pass you're data model to you're cell. and then share that through you're delegate not share you're cell, like:

protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieModel)
}

passing data from button in cell to another tableview?

The first thing I would do is get rid of CartItem - It doesn't seem to be doing anything except wrapping an Items instance, and you have some confusion in your code as to whether you are using CartItem or Items (I would probably also rename Items to Item - singular).

class Cart {
static let currentCart = Cart()
var cartItems = [Items]()
}

To get the "add to cart" action from your cell you can use a delegation pattern or provide a closure to handle the action. I will use a closure

class MenuCell: UITableViewCell {

@IBOutlet weak var name: UILabel!
@IBOutlet weak var category: UILabel!
@IBOutlet weak var productImage: UIImageView!

@IBOutlet weak var weight: UILabel!
@IBOutlet weak var price: UILabel!

@IBOutlet weak var addToCart: RoundButton!

var addActionHandler: (() -> Void)?

func configure(withItems items: Items) {
name.text = items.name
category.text = items.category
image.sd_setImage(with: URL(string: items.image))
price.text = items.price
weight.text = items.weight
}

@IBAction func addTapped(_ sender: UIButton) {
self.addActionHandler?()
}

}

Now, in your menu cellForRowAt you can provide the action handler:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuCell") as! MenuCell // Just crash at this point if there isn't a valid cell identifier configured
let item = itemSetup[indexPath.row]
cell.configure(withItem: item)
cell.addActionHandler = {
Cart.currentCart.items.append(item)
}
return cell
}

And that should be all you need to do - When you segue to the cart view controller, it will show the current contents of the cart.

Note that you could improve your cart data model somewhat by allowing it to have a quantity for each item and providing an add(item:) function that incremented the quantity if the item was in the cart

How to pass data on button clicked in cell to another tableview?

Just create a protocol to create a delegate and assign it to your cart class when the cell is initialized

protocol ItemCellDelegate {
func itemCell(didTapButton button: UIButton)
}

Then have a delegate property in the ItemCell

class ItemCell {
weak var delegate: ItemCellDelegate?
...
// Then call the delegate method when the buttons is tapped.
func buttonTapped() {
delegate?.itemCell(didTapButton: theCellsButton)
}
}

Then make your Cart conform to the delegate

extension Cart: ItemCellDelegate {
func itemCell(didTapButton button: UIButton) {
// Do you stuff with button, or any other data you want to pass in
}
}

Then set the delegate before the cell is returned.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CartCell", for: indexPath) as! CartCell

let cart = Cart.currentCart.CartItems[indexPath.row]
cell.qty.text = "\(cart.qty)"
cell.lblMealName.text = "\(cart.items.category): \(cart.items.name)"
cell.lblSubTotal.text = "$\(cart.items.price1 * Float(cart.qty))"

cell.delegate = Cart.currentCart //You should rename this static var to just 'current'

return cell
}

How to pass data from a table view cell class back to view controller with the table view?

Use a closure to call back button action from cell to view controller.

CustomCell

class CustomCell : UITableViewCell {

var ClousureBtnActionHandler:((_ sender: AnyObject) -> Void)?

@IBAction func btnInfoActionHandler(_ sender : AnyObject) {
if self.ClousureBtnActionHandler != nil {
self.ClousureBtnActionHandler!(sender)
}
}
}

ViewController

TableView Datasource

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : CustomCell = tableView.dequeueReusableCell(withIdentifier: "CustomCell") as! CustomCell
cell.ClousureBtnActionHandler = { sender in
print("Do any thing with your button action")
}
}

how to pass data from one Tableview to another Tableview when button is pressed in cell?

You can pass the values in closures.

So, in your Cell class you could change your closure var to:

 var addActionHandler: ((Int) -> Void)?

Then, in your addToCart button action, something along these lines:

@IBAction func atcBtn(_ sender: UIButton) {

// pass back the user selected values
var i = 0
switch lastSelectedButton {
case optionBtn1:
i = 1
case optionBtn2:
i = 2
default:
i = 3
}
self.addActionHandler?(i)

}

Create a .selectedOption property of your Items class, you should add one (of type Int). You can use that to track the user's selection.

Modify cellForAt in Cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { return UITableViewCell() }

// use var to make item mutable
var item = itemSetup[indexPath.row]
cell.configure(withItem: item)
cell.addActionHandler = { (option: Int) in
print("Option selected = \(option)")
item.selectedOption = option

Cart.currentCart.items.append(item)
}

return cell
}

In your CartCell you can make the labels like this:

    if items.selectedOption == 1 {
lblSubTotal.text = "$\(formatter.string(for: items.price1)!)"
lblWeight.text = "\(items.weight1)"

} else if items.selectedOption == 2 {
lblSubTotal.text = "$\(formatter.string(for: items.price2)!)"
lblWeight.text = "\(items.weight2)"

} else if items.selectedOption == 3 {
lblSubTotal.text = "$\(formatter.string(for: items.price3)!)"
lblWeight.text = "\(items.weight3)"

}

Passing data through tableView using the button clicked

You need to pass the cell as a parameter to the usernameClicked delegate method.

Then then the table view controller can ask the table view what the index path of the cell is. Then from the index path you can get the data you need.

Update the protocol:

protocol PostCellDelegate {
func usernameClicked(_ cell: PostTableViewCell)
}

Update the button handler:

@IBAction func usernameButtonAction(_ sender: Any) {
print("Username clicked")
self.delegate?.usernameClicked(self)
}

Add a property to your `DiscussionListTableViewController:

var clickedPath: IndexPath? = nil

Update the method in the view controller:

func usernameClicked(_ cell: PostTableViewCell) {
if let indexPath = self.tableView.indexPath(for: cell) {
clickedPath = indexPath
performSegue(withIdentifier: "viewProfile", sender: self)
}
}

Then in your prepare(for:), replace the use of:

let indexPath = tableView.indexPathForSelectedRow!

with:

if let indexPath = clickedPath {
// get the row
// access the posts data
}


Related Topics



Leave a reply



Submit