Perspective table of hyperlinks - table displays the HTML rather than a link

Ignition 8.1.

In my Perspective table binding I’m returning some columns one of which is in the form of a hyperlink:

[{"id":166,"wan":"<a href=\"10.12.34.56:8080\">10.12.34.56</a>","mac":"04:a1:51:72:b2:45"}]

The table is displaying the raw HTML. I want a link.

The SQL query is:

SELECT 
    CONCAT('<a href="', wan_ip, ':8080">', wan_ip, '</a>') 
    ...

Ignition is escaping my ". What am I missing?

Tables themselves will only render primitive data types within columns (strings, numbers, booleans). If you want to provide a link, you have two options:

  1. render the column as “view”, and create a separate View which contains a Markdown component. You’ll need to configure a param with a key of value for this View, and the markdown should bind its source property to the value param.
  2. Do the same thing as step 1, but use a Link component instead of a Markdown component. You’ll need to modify the incoming value to either be an object with keys of ‘href’ and ‘text’, or you can pass the data as-is - but you’ll need to strip the relevant datas out of the string.

I think solution 2 would be the best because you don’t have to build the link yourself. You would need to change the SQL query/transform to return an object like this (note that I’m ignoring “mac” because I don’t know how you’re using it):

[{"id":166,"wan":{"href": "10.12.34.56:8080", "text": "10.12.34.56"},"mac":"04:a1:51:72:b2:45"}]

Table.props.columns[x].render should have its value changed to “view”, and viewPath should point to your View which contains a link (we’l call it LinkView).

Within LinkView you should create a param with a key of value, and it should be an object. Within that object, you should provide two internal keys: “href” and “text”. Bind the properties of the link to these param values.

You’ll need to adjust the spacing of LinkView to fit your needs.

1 Like

Thank you for your detailed explanation. I’ll try this when I’m back at my desk.

Can I use this trick to display my IP addresses in the correct order so that “.3” comes before “.20”? (I’d have".003" and “.020” in the underlying data. )

You'd have to sort the data before sending it to the Table.

I have failed to get this to work yet.

I’ve created a view for the Link component. I’ve created the custom viewParams, named it viewParams (although this seems likely to be incorrect), entered some default values and bound the label’s href and text properties to parameters.

Then in the table column I’ve set

  • Render: view
  • viewPath: viewIpAddressLink
  • viewParams: this.props.data[2].wan

I’m still only getting the default text in the table column so I’ve messed up somewhere.

Can anyone point out my error?

1 Like

No, that is close, but you’ve applied the params in the wrong location. If you click the View node in the project browser (the node which you have named ViewIpAdressLink, you will see a category within the Perspective Property Editor called PARAMS.
You should set up a param property with a key of value, like so:
Screen Shot 2020-12-04 at 2.23.09PM

Thank you again. I’m nearly there.

Now I think the last task is to use a binding with transform on each parameter to extract the href and text values.

Am I close?

I don’t think you should need to do that… When a column sends data to a rendered view, it sends the column data along in an object with a name of value. You shouldn’t need to configure any binding on the table itself.

Update:
I’ve verified this locally. you don’t need to perform any bindings or transforms on the Table or its associated columns. All you need to ensure is that the data for the COLUMN is an object, and that object has at least the two keys: href and text. If this is done correctly, and you have a param configured as I described within your ViewIpAddressLink View, then the Link will work.

Thank you for your patience! I've spent many hours trying to understand how this works. Some understanding has come but I haven't succeeded completely.

Here I have an embedded view of my viewIpAddressLink. If I specifically pass a value object with the href and text key/value pairs it works.

If I pass the JSON object as a value string it doesn't work.

The object I'm testing with is:

{"href": "http://bonkers.com", "text": "Bonkers"}

All you need to ensure is that the data for the COLUMN is an object, and that object has at least the two keys: href and text.

I have my SQL query returning the column data in the JSON object format as shown above.

What am I missing?

No, that won't work because as you said: you're sending a string - not an object. When it comes to Perspective properties, Strings are NOT objects, even if they represent a JSON object converted to a String. Strings are JSON primitive types, and will always be read as a String.

I would need to see how you're supplying this data to your Table, but what I would recommend is looping over the data you're getting back from the query. Are you using a Named Query binding, or do you have this data in a Tag or property somewhere?

Let's look at a simplified example where I have a Query binding which returns id, ip, text, and location (for ease-of-use I've specified my data should be returned as a JSON):
Screen Shot 2020-12-07 at 12.49.53PM

I then apply a Script transform to that returned query:

# make a new empty list
rows = []
# loop over returned rows of query
for entry in value:
    #make a new row_object for each row
    row_object = {}
    row_object['id'] = entry['id']
    #make a "link" object which contains "href" and "text" as keys
    row_object['link'] = {"href": entry['href'], "text": entry['text']}
    row_object['location']
    rows.append(row_object)
return rows    

In my simplified example there is only one row, and this transform results in an array with this shape:
Screen Shot 2020-12-07 at 12.56.37PM

Now if you configure a Table column to use a field of "link", it will map the link object to that column. When the column passes the data to the View which will be used within the column it will pass href and text (NOT link). The View being used will receive these keys in a value object where href and keys are children (see previous post in this thread).

Success!

Thanks for sticking with me on this. I was surprised at how complicated this got compared with, for example, MySQL and PHP rendering of a table of links. I didn’t think I’d need a script or even a rendered view to do the task. I can see, however, the power and flexibility that Perspective gives on this.

Problem solved.

1 Like

I have something similar here. But I am generating the URL as a string within SQL.

I have created a subview with a Link object and a simple string parameter that passes that string into the link via binding.

My problem is how to bind the column in the table to the URL string the column is referencing....

Please paste an entry from your data here. We don't need the whole list of data entries, just one from among your data. Please also designate which key from among the entry contains the information to be present in your link.

URL for a record (edited to hide content). There are no keys, just the https:// page in string form...
"https://XXXXX.sharepoint.com/sites/XXXXX/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FXXXXX%2FShared%20Documents%2FYYYYY%20YYYYY%2FIN%2FH%20Series%2FPRODUCT%20BATCH_NO.pdf&parent=%2Fsite...

There must be a key for the Table to make any use of the data within a column configuration or subview. You're going to either need to transform the data you're feeding to the table, or alias the url in your SQL query.

oops, misunderstanding there. the key is a field called BATCH_NO

image

No, the key is PDFURL. So your column should use the field property to target the PDFURL column of your data.

I thought you meant the primary key... gotcha. That's done.

image

With that structure in place, I believe your subview should just expect a param called value. Your Link component should then bind the url and text props against the value param.