PSA: Link to recently created rows by UID, not RowID()

Requirement: with a button create a row and bring it up into focus (e.g. as a modal)

Problem: to bring out a row into focus, you need its RowID() so that you could construct its URL like:

OpenWindow(Format("#_tu9Wb/r{1}&modal=true", CreatedRow.RowID())

However, RowID() at this point may still be blank because the row is not yet stored to the server. And it will always stay blank if the doc is used in Play mode.

Solution: instead of RowID() use “true” 10-alphadigit unique row ID (UID) that is created on browser side as soon as the row itself is created.

One idiom to get this UID is by formula:

Split(thisRow + "", "/").Last()

The thisRow + "" returns grid-xxxxxxxxxx/i-xxxxxxxxxx table/row UID pair (which, I believe, is used internally to compare row references against each other), and we use Split("/").Last() to only cut off the row UID part.

Now you can use this identifier right away in your URLs.
Heads up: instead of r<RowID> parameter you’ll have to use ru<UID>, like:

OpenWindow(Format("#_tu9Wb/ru{1}&modal=true", CreatedRow.UID)

so that instead of /r123 your link looks like /rui-12345XzYuW.

E.g. here’s a button that creates a “helper table” row if it doesn’t exist (I’m using a helper table as a form to submit cross-doc updates), and immediately opens it as a modal:
image

This is one of the pro-tips that let you build docs that feel a lot like apps. There’ll be many more like this one on codatricks.com :slight_smile:


P.S. Updated one of my older demos. Play around with this embedplay: create rows and see how UIDs are added immediately and row IDs are not. Then click the “Pop me up” button and see that popups by UID work just fine :slight_smile:

8 Likes

That’s awesome!! keep them going :fire:

Peculiar behavior fact: links with UIDs don’t always work. There’s one case when they don’t:

  • When UID contains an underscore _
  • AND RowID is already present

If both of these conditions apply, the link with /rui-xxxxxxxxxx will not properly convert to a canonical row link with Row ID like it usually does. When there’s no underscore or there’s no RowID yet, it will always work.

Yet another update. Instead of manually figuring out whether to use ID or UID, you can just build your link with:

OpenWindow(thisRow.Url() + "&modal=true")

and the thisRow.Url() will automatically resolve to either _rui-xxxxxxxxxx format for rows with no Row ID, or to _rXXX row ID format for those that already have one.

If you need an URL based on a view of this table, you can always trim the ID/UID part from row’s URL like this:

thisRow.Url().Split("/r").Last()
2 Likes

Hi @Paul_Danyliuk, I wonder if I’m running into this observation you’ve made when it comes to implementing your UID procedure into my doc. I followed your instructions on adding different buttons which open different views of a row. The purpose was to create a sort of “menu” for easy navigation while on mobile.

It works perfectly on mobile. But when I click the button on desktop, the URL will change while the view will not change on screen. When I first open a row (into any view) I can make edits to the row and click one of the other-view buttons. The first button click will work to change the view, but the second button click will not change the view.

Any advice? Thank you :pray::heart:

Could be that, yeah. That’s why better use the updated technique with Url() that always resolves to Row ID but falls back to UID when Row ID is not present.

There’s another thing too. Focusing on a row doesn’t reliably work (or always doesn’t work IIRC) when the view is in the same section as the button that you’re clicking. Could be that too.

In any case, hard to say without seeing the doc.

I tried using your thisRow.Url().Split("/_r").Last() formula, but got errors. Realized it was the /_r should be /r

Now it works as it did before with this syntax:

OpenWindow(Format("#_tuD-A/r{1}&modal=true", thisRow.Url().Split("/r").Last())

The behavior is the same as when using the raw UID :frowning: For some reason I cannot click to different views while in the same row’s modal…

Frankly it’s alright. I can just press esc to go back to table view, then press the other button as needed. Please let me know if you can reproduce this issue…

  • having multiple buttons for different views on a single modal
  • clicking between different views for the same row
  • behavior broken on desktop while perfect on mobile
  • using thisRow.Url().Split("/r").Last() to get the rID or ruID as necessary

This solution seems to work when executed alone, but if I execute the OpenWindow inside RunActions(), with some actions before, it sometimes prompt me to accept link navigation (and accept won’t work, only possible action is closing that modal), sometimes it will open a new tab to the origin table, and sometimes the notification says “[…] hyperlink executed” but nothing happen.

Maybe you can help me:
I am trying to create a button in one table (1) that executes several actions, like creating a row in other table (2), link it to a lookup column in current table, and then open a modal to edit the newly created row. Even more complicated, I would like it to work in the expanded detail of the first table.

  RunActions(
        AddOrModifyRows(
            db_attachments, _aux=Concatenate(thisRow.Nombre,thisRow.ID), 
            _aux, Concatenate(thisRow.Nombre,thisRow.ID)
        ),
        ModifyRows(
            thisRow, thisRow.[docs], 
            ListCombine(
                thisRow.[docs], db_attachments.Filter( _aux = concatenate(thisRow.Nombre,thisRow.ID))
        ).filter(IsNotBlank(CurrentValue))),
       OpenWindow(
           Concatenate(thisDocument.Url(), "_suZSC#_tuqlF/r", thisRow.[docs].Last().Url().Split("/r").Last(), "&modal=true")
       ),
       ModifyRows(
           db_attachments.Filter(_aux = concatenate(thisRow.Nombre,thisRow.ID)), db_attachments._aux, ""
     )
   )

As you can see, first i create a row in table “db_attachments” and assign it an aux id so current table can find it, then I add its reference to current table, and then I try to open a modal (i have tried lots of combinations, I am aware this isn’t the most robust solution but i was desperate to try to make it work).

This actions are executed in a button in current table. When this is run, it won’t work, yet if I add another button just with the OpenWindow command it does work. So I guess it has to do with the ID / UID thing, since the only difference is when I click the second button, the row is already created.

And now, the question of the million dollars, I was trying to make this work in a expanded view for the current table: use case is you are examining detailed view of current table row, then you want to add it a related document so you should click this button, new empty document should add to the documents table, and then a modal to enter its data should open. When you manually do this, you navigate to this modal, but in the top left corner it reads " < Back" and you can go back to the previous modal.

Sorry, I tried to explained best way I could. I didn’t shared doc because its a huge doc, in spanish, and probably would be completely messy. I am doing to keep track of projects and processes in my small company.

-------------------------Update: solved-----------------------------------
Just working a bit more around this, i found a solution. Issue is related to Paul’s comment
Problem is new rows for me have an UID “_rui-41213…” with underscore, always
I found a simple solution: Instead of thisRow.Url().Split("/r").Last(), you can use thisRow.Url().Split("/_r").Last().Split("/r").last()

1 Like

There is a simple solution that works in every case:

Instead of: thisRow.Url().Split("/r").Last()
Use: thisRow.Url().Split("/_r").Last().Split("/r").last()

So when referring to a new row, you should use something like

OpenWindow(
        Format(
                "#_tu5lK/r{1}&modal=true",
                thisRow.Url().Split("/_r").Last().Split("/r").last()
        )
)

It will extract the components even when the underscore is present in the UID

1 Like

Time to amend the answer.

No need to work around including/not including the underscore. This idiom will work:

OpenWindow(Format(
  "#_viewID/{1}&modal=true",
  thisRow.Url().Split("/").Last()
))

In case you’re calling this from a different table, you have to create a column to store either the URL or the rID/UID part on the target table, and then refer to that column in your button on another table. The reason here is that thisRow.SomeLookupColumn.Url() will not return the URL of the object in that lookup cell, but the URL of the lookup cell itself (actually just the URL of thisRow, but it’s still not the one that you need). This is similar to how Modified()/ModifiedBy()/Created()/CreatedBy() don’t return respective properties of objects in lookup cells, but such properties of the lookup cell itself.

P.S. Seems like Row IDs are now assigned in Play Mode as well. They are fake and reset when you reload the doc, but at least you can now safely use them in all scenarios and don’t have to use UIDs unless you specifically need them.

4 Likes

Great thread. Would be great if we could define our own user functions.

There seems to be a simple way to handle this now. Using Activate() with AddRow() in a button will create a new row and open the modal for editing. You can do this in the Button editor without code, but if you need to edit the function this approach should work.

Activate(AddRow(Table, Column, ColumnValue…))

This also seems to work, and allows you to select which view to open to:

AddRow(Table, Column, ColumnValue…).OpenRow()

4 Likes

Hi Paul … Is this recommendation still current? When I try to construct the Url using the Format function, I keep getting an error that says “thisRow” is not a valid object. I was just curious if there was an update to this post. Thank you.

Oops never mind. I got it to work using this formula in the button action AddRow([Base Table]).OpenRow([View of Base Table], “Modal”) Credit to @crocus for this workaround.

2 Likes

Yes, the overall thread lost its initial relevance:

  • RowID() now works in Play Mode: they are generated (but of course not stored to the doc)
  • For opening recently created rows, you should now use an OpenRow() formula. URL manipulation is now obsolete.

There are still cases where you’d need the UIDs:

  • For an immediately available row ID that doesn’t depend on servers congestion, throttling, you being offline etc.
  • For exposing these to APIs
  • For a pseudo-random ID that doesn’t give away the order or amount of rows in your table etc. Imagine a situation where you share the table of Orders along with these Row IDs with a client and you’re trying to make an impression of yourself as a very in-demand company. But if the client sees that there are not many Row IDs between the orders they placed for you, they can realize that perhaps you weren’t telling the truth.
2 Likes

Thank you for the clarity on this Paul as well as the previous workarounds that you posted to the community. My Coda learning journey is like a relay race. Race Leg 1 is the discovery that there isn’t an obvious way to do something but it is possible with workarounds (because pretty much anything is possible in Coda). Race Leg 2 is you and the many other advanced Coda doc builders figure out the workarounds. Race Leg 3 is that Coda builds it into the app natively and makes it more easily accessible for “no coders” like me (e.g. Personal Filters). Race Leg 4 is a community member will document the native way to do something in Coda. Even though it is tempting to just learn the “Race Leg 4” part, I am finding that developing an appreciation for and understanding of Race Legs 1, 2, & 3 is tantamount to building my confidence in Coda building. I appreciate your Race Leg 2 workaround on the issue of custom views for recently created rows from a button action. Hope this makes sense … was feeling the need to share!

4 Likes