This post is a follow-up to a question in the comment section on a previous post called Adding a new column in a M3 List. The question was how to add a clickable hyperlink in a new list column. This could be solved in a generic way by creating your own data template and template selector or by reusing existing functionality in MForms. In this post I will just cover the second part by reusing existing functionality. The more generic solution for custom content in list cells might be covered in a future post.
The example script in the end of this post shows how to a new list column with a hyperlink. When the link is clicked a message dialog is shown which shows the content of the first list cell in the selected list row. The script can be used as a starting point for doing something more useful such as launching a new task with parameters that uses data from the selected list row.
Script overview
The Init function subscribes to the Requested event so that it can disconnect event handlers and avoid memory leaks. It then uses the Dispatcher to call the InitializeColumn method with a slight delay to let the panel render before it is modified.
The InitializeColumn function adds a click handler for hyperlink clicks. The MForms list also has a handler for this but we will construct the column so that the standard MForms handler does not handle the hyperlink click. The next thing is to check if the column has already been added using the HasColumn function. If the column is not in the list it is added using the CreateColumn function. The next step is to add the data for the new column to each list row. This is only done if the extra list cell has not been added already which would be the case for the first list rows after a page down request for example.
The CreateColumn function creates a new GridViewColumn and sets an instance of ListCellTemplateSelector as the cell template selector. The Hyperlink property on the ListCellTemplateSelector is set to an empty instance of the Hyperlink class which is part of the personalization classes in Smart Office. When the Hyperlink instance is empty a hyperlink will be generated but the MForms click handler for hyperlink clicks will ignore it which means that we can handle the click instead.
The OnClickHyperlink function handles the click event for the added hyperlink. In this example I just get the value for the first list cell of the selected list row and show it in a message dialog.
import System; import System.Windows; import System.Windows.Controls; import System.Windows.Data; import System.Windows.Media; import System.Windows.Markup; import System.Windows.Threading; import MForms; import Mango.UI; import Mango.UI.Services.Lists; import System.Windows.Documents; package MForms.JScript { class HyperlinkColumnTest { var columnTag = "LinkColumn"; var debug; var controller; var listView; public function Init(element : Object, args : Object, controller : Object, debug : Object) { this.debug = debug; this.controller = controller; controller.add_Requested(OnRequested); var action : Action = InitializeColumn; Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, action); } public function OnRequested(sender : Object, e : RequestEventArgs) { try { if (controller != null) { controller.remove_Requested(OnRequested); controller = null; } if (listView != null) { var handler : RoutedEventHandler = OnClickHyperlink; listView.RemoveHandler(Hyperlink.ClickEvent, handler); listView = null; } } catch (ex) { debug.Error("OnRequested", ex); } } private function InitializeColumn() { try { this.listView = controller.PanelState.ListControl.ListView; var handler : RoutedEventHandler = OnClickHyperlink; listView.AddHandler(Hyperlink.ClickEvent, handler); var gridView = listView.View; var columnCount = gridView.Columns.Count; var lastIndex = columnCount - 1; var columnHeader = "Link"; var linkText = "Link"; if (!HasColumn(gridView, columnTag)) { columnCount++; lastIndex++; gridView.Columns.Add(CreateColumn(controller.PanelState.ListControl, lastIndex, columnHeader)); } for (var row in listView.Items) { if (row.Items.Length < columnCount) { AddCellsToRow(row, columnCount); row.Items[lastIndex] = linkText; } } listView.Items.Refresh(); } catch (ex) { debug.Error("InitializeColumn", ex); } } public function OnClickHyperlink(sender : Object, e : RoutedEventArgs) { try { if (e.OriginalSource != "System.Windows.Documents.Hyperlink") { return; } e.Handled = true; var row = listView.SelectedItem; if (row != null) { var message = "Value in first column: " + row[0]; ConfirmDialog.ShowInformationDialog("Hyperlink clicked", message); } } catch (ex) { debug.Error("OnClickHyperlink", ex); } } private function HasColumn(gridView, tag) { for (var column in gridView.Columns) { if (column.Header.Tag == tag) { return true; } } return false; } private function AddCellsToRow(row, cellCount) { var items = new Object[cellCount]; row.Items.CopyTo(items, 0); row.Items = items; } private function CreateColumn(listControl, index, headerText) { var column = new GridViewColumn(); var selector = new ListCellTemplateSelector(index, listControl.Columns); selector.Hyperlink = new Mango.UI.Services.Customization.Hyperlink(); column.CellTemplateSelector = selector; var header = new GridViewColumnHeader(); header.Tag = columnTag; header.VerticalContentAlignment = VerticalAlignment.Top; var textBlock = new TextBlock(); textBlock.Text = headerText; textBlock.Margin = new Thickness(2); header.Content = textBlock; column.Header = header; return column; } } }
Which version of Smart Office is required for this to work? I tired to apply this script but I only get a column with header created. No links on the lines.
It should at least work with Smart Office 10.0.5.x but it might work with slightly older versions. The lowest version I have verified it to work with is 10.0.5.4.
Ok, we are running 10.0.5.1.46 so that might be the reason.
The script required Smart Office 10.0.5.2 since ListCell was used with Hyperlink. Turns out you don’t actually have to use ListCell in this case so the script can be modified to work in 10.0.5.1 and probably somewhat older versions as well.
Replace these lines:
var cell = new ListCell();
cell.Text = linkText;
row.Items[lastIndex] = cell;
With this line:
row.Items[lastIndex] = linkText;
I will update the script in the post as well.
Yes, now it works also in 10.0.5.1. Thanks alot for your help!
I think the script is triggering on clicks on the list header and scrollbars as well. To solve this I added a condition in the OnClickHyperlink to look for the source of the click.
e.OriginalSource==”System.Windows.Documents.Hyperlink”
That is correct, I have updated the example code.
Hi,
I need to give a link at every row of the list which will take the user to another program whith the details of the selected row.
Can you help me out with this….
You need to investigate if the program you would like to navigate to supports bookmarks and if you have all the data (keys) available in the list.
That is the first step. Once that is done you build the URL but remember to URLencode the parameters after building the data together. In Mforms there is a class MForms.Mashup.Bookmark that can be used to create the bookmark.
I have done a hardcoded example that calculates the URL you need to appy this to your example and get the live data from the row. The example shows how to build a bookmark in JScript. You can check the MForms.Mashup.Bookmark documentation in the Mashup SDK API documentation or in the API documentation for the Smart Office SDK. Since the class is in the Mashup namespace it should be part of the API documentation that is available in the Mashup Designer.
This is a simple example of building the bookmark so you need to combine that with the other information on how to get data from the row.
import System;
import System.Windows;
import System.Windows.Controls;
import MForms.Mashup;
import MForms;
import Mango.UI.Services;
package MForms.JScript {
class ButtonTest {
var content, debug, button;
var controller;
public function Init(element: Object, args: Object, controller : Object, debug : Object) {
debug.WriteLine("Script Initializing.");
if(element != null) {
debug.WriteLine("Connected element: " + element.Name);
}
this.controller = controller;
this.debug = debug;
content = controller.RenderEngine.Content;
var button : Button = new Button();
button.Content = "Test";
button.Name = "addShortcutButton";
Grid.SetColumnSpan(button, 10);
Grid.SetRowSpan(button, 3);
Grid.SetColumn(button,50);
Grid.SetRow(button,1);
content.Children.Add(button);
controller.add_Requested(OnRequested);
this.button = button;
button.add_Click(OnClick);
}
public function OnClick(sender: Object, e: RoutedEventArgs) {
var bookmark = new Bookmark();
bookmark.Program="MMS001";
bookmark.Table="MITMAS";
bookmark.KeyNames="MMCONO,MMITNO";
bookmark.Option="5";
bookmark.Panel="E";
bookmark.AddKeyValue("MMITNO","1000"); // TODO you should get the value from the selected line
bookmark.AddKeyValue("MMCONO",UserContext.CurrentCompany)
var uri = bookmark.ToUri();
debug.WriteLine(uri);
DashboardTaskService.Current.LaunchTask(uri);
}
public function OnRequested(sender: Object, e: RequestEventArgs) {
button.remove_Click(OnClick);
controller.remove_Requested(OnRequested);
}
}
}
HI,
This Blog is really Good for Infor Developer
I am New Developer of Infor.I have done scripting exercise its working perfect but where to uploaded jscript file?
Please help me!
Hi,
Both M3 and S3 have a ScriptDevelopers guide as part of the documentation. It contains information on how to upload the jscript file. You must be an Smart Office Administrator to upload the jscript file and the process differs with version. The Scripting Guide also contains important information that you should read before deploying jscripts. Those guides are part of the download zip when you download the software. Contact your system administrator or Infor support and they’ll help you further.
Hi Karinpb,
Thanks for your reply.
I got the solution in ISO Document.
Hi Karin,
Is it possible to add a hyperlink to existing columns? Hyperlink will have to come from a certain fields retrieved via API.
Yes, it’s possible. But I don’t have an example for it. Just make sure that you get the values you need via API once the link is clicked and not before that. This is good requirement and I have created an enhancement suggestion to allow a personlization to be a link that will trigger a JScript. Such an enhancement would make this scenario easier to achieve.
Hi,
Was working with Thibaud and looks like this is already in place. Thank you.
Great. Ask him to write a post on it. I did find an example of showing an image as a tooltip.
This is great. Can I get the whole code for this? Sorry still new to jscript 🙂
Hello,
I need help for addig a Hyperlink in new column in H5 just like smart office “Link column”, Can you please post a code?
Thank you.