How to Call Swiftui Navigationlink Conditionally

How to call SwiftUI NavigationLink conditionally?

Anyway it should be a button... something like

ScrollView(.vertical) {
ForEach(photos, id: \.self) { element in
Button(action: {
// here call a function with callback provided if password
// verification passed
self.checkPassword { verified in
if verified {
self.photo = element // store tapped element
self.isFired = true // << this might be called async
}
}
}) {
Image(uiImage: element.image)
}
}
}
.background(
// activate link for tapped photo
NavigationLink(destination: ImagePreviewView(photo: self.photo),
isActive: $isFired) { EmptyView() }
)

Change NavigationLink destination conditionally in SwiftUI

I assume you want to look at the element and to determine what view to show, the following achieves that. You can also use an enum for this.

The Collection passes in the element, so you can use that and a conditional:

struct ProjectView: View {
var row: ItemsGroupModel
var body: some View {
Text("Project title = \(row.title)")
}
}

struct NonProjectView: View {
var row: ItemsGroupModel
var body: some View {
Text("Non-Project title = \(row.title)")
}
}

// row type of the collection view
struct ItemsGroupRow: View {

var data: ItemsGroupModel

var body: some View {

// This model is for one row
// I need to specify what view to open depending on what item of the collection view was selected (clicked on)
NavigationLink(destination: {
VStack{
if data.title.contains("project") {
ProjectView(row: data)
} else {
NonProjectView(row: data)
}
}
}()) { // open ProjectsView only if the user clicked on the item "Projects" of the list etc..
Text(data.title)
}
}
}

Note: I think the collection does have some bugs.

Example using enum which does not work correctly:

import SwiftUI

struct ConditionalNavigationLinkView: View {
var body: some View {
GroupDetail()
}
}

// data displayed in the collection view
var itemsGroupData = [
ItemsGroupModel(.project), // should open ProjectsView()
ItemsGroupModel(.people), //should open PeopleView()
ItemsGroupModel(.agenda), //should open AgendaView()
ItemsGroupModel(.name) //should open NameView()
]

// main view where the collection view is shown
struct GroupDetail: View {

var body: some View {

NavigationView{
// FAMOUS COLLECTION ELEMENT
Collection(itemsGroupData, columns: 2, scrollIndicators: false) { row in
ItemsGroupRow(data: row)
}
}
}
}

enum ItemsGroupModelType: String {
case project = "Projects"
case people = "People"
case agenda = "Agenda"
case name = "Name"
}

// model of the data
struct ItemsGroupModel: Identifiable {
var id: UUID
let type: ItemsGroupModelType

init(_ type: ItemsGroupModelType) {
self.id = UUID()
self.type = type
}
}

struct ProjectView: View {
var row: ItemsGroupModel
var body: some View {
Text("Projects \(row.type.rawValue)")
}
}

struct NameView: View {
var row: ItemsGroupModel
var body: some View {
Text("NameView \(row.type.rawValue)")
}
}

struct PeopleView: View {
var row: ItemsGroupModel
var body: some View {
Text("PeopleView \(row.type.rawValue)")
}
}

struct AgendaView: View {
var row: ItemsGroupModel
var body: some View {
Text("AgendaView \(row.type.rawValue)")
}
}

// row type of the collection view
struct ItemsGroupRow: View {

func printingEmptyView() -> EmptyView {
print("type: \(data.type.rawValue)")
return EmptyView()
}

var data: ItemsGroupModel

var body: some View {

// This model is for one row
// I need to specify what view to open depending on what item of the collection view was selected (clicked on)
NavigationLink(destination: {
//print("Hello")

VStack{
self.printingEmptyView()
if data.type == .project {
ProjectView(row: data)
}
if data.type == .people {
PeopleView(row: data)
}
if data.type == .agenda {
AgendaView(row: data)
}
if data.type == .name {
NameView(row: data)
}
}
}()) { // open ProjectsView only if the user clicked on the item "Projects" of the list etc..
Text(data.type.rawValue)
}
}
}

How to put a condition to NavigationLink? SWIFTUI

Well, your question can be interpreted differently...

  1. if you want to don't show the ability to go next until score is bigger that target at all, then it is

    if score > target { // link will appear to user only when true
    NavigationLink(destination: level2()) {

    Text("Next Level")
    }
    }

  2. if you want to show link but don't allow to navigate until condition is true, then it is

    NavigationLink(destination: level2()) {

    Text("Next Level")
    }.disabled(score <= target)

  3. if you want automatically navigate link when condition is true, then the possible variant is (but note - in such case you need manually manipulate back-forward navigation, or disallow back, etc.)

    NavigationLink(destination: level2(), isActive: .constant(score > target)) {

    Text("Next Level")
    }

  • alternate is to use explicit state for activation

How to navigate using button with condition check in SwiftUI

You can do something like this:

    NavigationView {
VStack {
NavigationLink(destination: Dashboard(userName: self.userId, password: self.password), isActive: $showDashboard) {
Text("")
}
Button(action: {
if self.userId.isEmpty || self.password.isEmpty {
self.isAlert = true
} else {
self.showDashboard = true
}
}) {
Text("Submit")
.foregroundColor(.green)
.font(.system(size: 22))

}
}
}

A thing to remember is that a NavigationLink is a button itself and when pressed it navigate to the destinationView, the isActive parameter is a way to force that to happen (without the user clicking the NavigationLink). As of now I'm not sure how to embed logic into NavigationLinks.

Hope this helps :)

EDIT:

Another thing you can do is the following:

NavigationLink(destination:Dashboard(userName: self.userId, password: self.password)) {
Text("Submit")
}.disabled(self.userId.isEmpty || self.password.isEmpty )

This would disable the NavigationLink until both input fields are not empty.



Related Topics



Leave a reply



Submit