Can I apply a filter dynamically to List lookup on Nintex Forms 2013? - sharepoint

I have a requirement wherein I need to filter the List lookup dynamically. My list has a column called category that can either contain value 'A' or 'B'. Then there is a field -'Selection' on the Content type that can either take value 'A' or 'B' or 'All' . If its 'A' I need the List lookup to take rows where category = 'A' , same goes for'B'. However if the 'Selection' is - 'All' then I need to display all the items from the list.
I was thinking of filtering the List lookup for the column - 'Category' . But the problem is as I am on a content type form , I do not have any variables that can be set dynamically.
I can not use the Filter by control mapped to 'Selection' as the it does not work when the selection is 'All' (There is no value called 'All' under category in the list).
I tried using a calculated value that operates on a formula and tried using it in Filter by specific value in List lookup , but the filter doesn't work as the list lookup loads before the calculated value on form load and hence the calculated value is always empty for the filtering.
Is there any way I can achieve this functionality.
Thanks in advance

I have thought of two solutions to this problem.
Have 3 separate list lookup controls that are laid over top of each other. Filter one by A, one by B, and let one have no filter. Then create rules to show the one with the filter you want to show, and hide the others. To save the value, you'd have to use JavaScript to copy the value from the list lookup to a hidden text box when one of the controls changes value. This solution isn't great and gets worse if you have more options...but it works.
You can use JavaScript to filter the list based off the Selection. This is a little more tricky, but you wouldn't need more lookup controls for more options. You would need only 2 list lookups no mater how many options you have for Category/Selection. You need one that shows the info that you want the user to chose from (unfiltered) and the other is from the same list, and same view, but the column should be the Category column ( you can hide this lookup with javascript). This is the code I used to get what you are describing.
//get the original html to 'reset' the dropdown after a change
var originalTitle = NWF$("#" + title).html();
//when the selection changes
NWF$("#" + selection).change(function () {
//put the original html in the dropdown to check all the options
NWF$("#" + title).html(originalTitle);
//get the new value of the selection
var choice = NWF$("#" + selection + " :checked")[0].value
//if choice is all then we are done because the original html is in the dropdown again with all the options
if (choice == "All") {
return;
}
//create the array where you will store the ids of the options that match the choice
var filteredIds = [];
//for each option in the category drop down, see if the text matches the choice (this is your filtering)
NWF$("#" + categoryDD + " option").each(function (i, n) {
//if the text of the option matches the choice add the id to the array.
if (n.text == choice) {
filteredIds.push(n.value);
}
});
//initialize string of html
var filteredTitlesHTML = ""
//for each of the ids in the list, get the option html with that id from the title dropdown and add it to the resulting HTML string
NWF$(filteredIds).each(function (i, n) {
filteredTitlesHTML += NWF$("#" + title + " option[value = '" + n + "']")[0].outerHTML
})
//put the html in the dropdown to show only filtered values
NWF$("#" + title).html(filteredTitlesHTML);
})
You can see in the picture the javascript variable names I gave the controls to use the javascript I have provided.

Related

How does sibling or siblingAtRow() function works to retrieve the value from hidden Column in QTableWidget?

I have a database from which data is coming into a QTableWidget. The table in the database has the following Columns,
ID (Primary key, auto-increment value)
Name
Location
The QTableWidget has the following columns (that I have added)
ID (this column, I have hidden. and it contains the value of "ID" column from the Database Table)
Sr # (Represents the Row Number of the table)
Name (Contains "name" from the database table)
Location (Contains "Location from the database table)
Actions (Contains a Delete Button for that Row)
By hidden, I mean to say that I have made this column hidden using the folliwng command,
self.ui.table.setColumnHidden(0, True);
This is how I am populating my QTableWidget and creating a Delete Function,
def get_data(self):
mycursor = self.DB.cursor()
Subquery = "select id, name, location "
Subquery += " from tbl_person"
mycursor.execute(Subquery)
numcols = len(mycursor.fetchall()[0])
mycursor.execute(Subquery)
numrows = len(mycursor.fetchall())
self.ui.table.setRowCount(numrows)
self.ui.table.setColumnCount(numcols+2)
mycursor.execute(Subquery)
tablerow = 0
for row in mycursor.fetchall():
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
delete_button = QPushButton("Delete Data")
delete_button.clicked.connect(self.executeDeleteFunction)
# delete_button.setStyleSheet(delete_push_button) -> Only for styling
self.ui.table.setItem(tablerow, 0, PySide2.QtWidgets.QTableWidgetItem(str(row[0])))
self.ui.table.setItem(tablerow, 1, PySide2.QtWidgets.QTableWidgetItem(str(tablerow+1)))
self.ui.table.setItem(tablerow, 2, PySide2.QtWidgets.QTableWidgetItem(str(row[1])))
self.ui.table.setItem(tablerow, 3, PySide2.QtWidgets.QTableWidgetItem(str(row[2])))
self.ui.table.setCellWidget(tablerow, 4, delete_button)
tablerow += 1
self.ui.table.setColumnHidden(0, True)
#self.ui.registered_table.horizontalHeader().setSectionResizeMode(PySide2.QtWidgets.QHeaderView.Stretch)
self.ui.table.resizeColumnsToContents()
def executeDeleteFunction(self):
self.person_id = self.ui.table.selectionModel().selectedIndexes()[0]
self.person_id = self.person_id.row()
mycursor = self.DB.cursor()
sql = "delete from tbl_person where id = %s"
val = (id, )
mycursor.execute(sql, val)
print("Deletion Successful")
On the Deletion Function, what this code does is basically gets the value of the **Sr # ** Column from the QTableWidget and deletes the data according to that, i.e. it is getting me the value from the visible first column and not the actual first column. But, I want the data from the "ID" column of the QTableWidget which is hidden
I tried to look up on how to get the value from the first hidden column on the QTableWidget and ended up with this link: How to get data from hidden 'id' column in QtableWidget
This apparently solves my issue but I can not seem to make it work for my code. I don't want to retrieve values of multiple Rows but only of one row so how do I do this (as I am only deleting one row. But in the question mentioned, I believe that it is getting data from multiple rows due to that for each loop)?
Moreover, I tried to find help regarding the functionality of sibling function (which is provided in the answer of above question) however I could not find any good resource on this function (i.e. how to use this, or some practical example and etc.)
I tried the following with Sibling function to obtain the value of first hidden column of the Selected Row but it did not work,
self.value = self.table.selectedItems()[0]
self.value = sibling(self.value.row(), 0)
There are some conceptual problems with the given code.
First of all, the QtSql module should be preferred instead of artificially creating a model. For basic tables, QSqlTableModel is fine enough, while for custom queries, QSqlQueryModel is a good choice.
Now the problem is that UI-based selection is always based on visible items: if you select a row in a view that has hidden columns, you will not get the hidden indexes that belong to those columns.
In order to get the indexes (as in QModelIndex) of hidden columns on a table widget, the only way is the same for a table view: you need to access the model and get the index for the row, or you get the actual model index and then get the sibling (which is conceptually the same, as the underlying function does):
item = self.table.selectedItems()[0]
index = self.table.indexForItem(index)
firstRowIndex = index.sibling(index.row(), 0)
sqlIndex = firstRowIndex.data() # might be a string
Note that you can also use siblingAtColumn():
firstRowIndex = index.siblingAtColumn(0)
That's because when you create QTableWidget items, you're actually creating a new model, and the row for that model doesn't reflect the actual "row" of that index in the source model; items in the second row will return 1 for row(), even if their actual row is different, and that's because that item has been added as second to the table widget, since it's the second item in the query.
So, the solution is that you either get the incremental row value for the first column index sibling, or you use one of the predefined Sql models.
For simple models, the latter solution is fine enough, but if you need more complex models, the first is certainly more accurate and reliable.

Xpages: how to use viewEnt.getColumnValues() to retrieve all relevant value when export data?

In the Xpage, it will display officer name, officer type and department (I use sessionScope variable to do that). There is a combobox to allow the user to select
the officer type that the user wants to compare. And then a button is used for export the data.
The export data will show the comparison between the document that the selected officer type needs to read and the document that the current officer has been read.
If the officer has read document that matches the selected officer type needs to read, it will show "Document has been read", otherwise, it will
show "Document has not read"
Due this post export data from panel let me know how to export data from panel, I begin to follow the code from the post and modify some code to fulfill the user requirement.
I have two views to do the comparison:
Each officer type needs to read various documents, so there is a view to store the value, the first column is the officer type and the second column is the document
that the officer type should read. The second column is multi value field and I am able to set the Multi-value separator is New Line.
Another view the includes officer name, the related officer type and document read by the officer.(no column for multi value)
I use #DbLookup and for loop to do the comparison and here is part of code:
var officer = sessionScope.Officer;
var officerType = sessionScope.OfficerType;
var showSelectedTypeDoc = #DbLookup(#DbName(),"view1", officerType, 2);
var showUserHasReadDoc= #DbLookup(#DbName(),"view2", officer, 3);
var result = "";
while (viewEnt != null)
{
if(viewEnt.getColumnValues()[1] == officer) //get the value related to the officer in the session
{
writer.write("<tr>");
for(var s = 0; s < showSelectedTypeDoc.length;s++) //loop in view1 first
{
for(var r = 0; r < showUserHasReadDoc.length;r++)//then loop the view2
{
if(showSelectedTypeDoc[s] == showUserHasReadDoc[r])//if value matches between 2 views
{
result = "Document has been read";
}
else
{
result = "Document has not read";
}
}
}
//display the list of the document category related to specific officer type
writer.write("<td>" + viewEnt.getColumnValues()[2] + "</td>"); //Problem occurs here, it only shows the first value, the appearance depends on the loop
writer.write("<td>" + result+ "</td>"); // only display the else part
writer.write("</tr>");
}
}
Actually I suppose
viewEnt.getColumnValues()[2]
will show all the relevant values, however when I export the value, it only display the first value e.g. [first value].
The code
writer.write("<td>" + result+ "</td>");
I review the if condition, it should be fine, but it only shows the else part
I tried
showSelectedTypeDoc[s]
instead of
viewEnt.getColumnValues()[2]
it shows undefined and the appearance depends on the looping.
But if I try
showSelectedTypeDoc[0] //or showSelectedTypeDoc[1], etc
it can show the correct value and the appearance depends on the looping.
However I will not know how many values that the variable stored, so I prefer
showSelectedTypeDoc[s]
to find all relevant values but not successful.
I start to think why it only shows the first value. I revise the code and the view, I guess probably is the multi value column cause the problem. It is because In Louts Client, in the view I only click once to particular value, if the value has multi value, it will show the "tick" symbol to relevant data.
So I would like to know to how to use
viewEnt.getColumnValues()[2]
to retrieve all the data related to a specific value. Grateful for your advice please. Thank you.
getColumnsValues() returns a Java Vector. So the syntax you need to get a specific element in the Vector is getColumnValues().get(2) (which will get the third column).
Getting a column values doesn't need it to be categorised. Categorisation is only required for retrieving the entry, not the column values.
I believe when using the index that static columns (e.g. with formula set to a static value like 1 or "<tr>") are skipped.

Highlight Duplicate list item in SharePoint 2013

I have a SharePoint 2013 (The Cloud version) custom list where 1 column is a text field where contact numbers are keyed in.
How can I get SharePoint to highlight duplicate values in that column so that every time a new item is added to the list, I'll know if the contact number has been used previously?
Ideally, here's what I'd get if I were to enter 816's details for the 2nd time:
CNO....Name.......Issue
816.....Blink........Login Problem (highlighted in red)
907.....Sink.........Access Denied
204.....Mink.........Flickering Screen
816.....Blink........Blank Screen (highlighted in red)
I've been struggling with this for awhile and would be very grateful for any advice. Thanks!
Since SharePoint 2013 uses Client Side Rendering (CSR) as a default rendering mode I would recommend the following approach. Basically the idea is to customize List View on the client side as demonstrated below.
Assume the Requests list that contains RequestNo column.
The following JavaScript template is intended for highlighting the rows when list item with RequestNo column occurs more then once:
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPostRender: function(ctx) {
var rows = ctx.ListData.Row;
var counts = getItemCount(rows,'RequestNo'); //get items count
for (var i=0;i<rows.length;i++)
{
var count = counts[rows[i]["RequestNo"]];
if (count > 1)
{
var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);
tr.style.backgroundColor = "#ada";
}
}
}
});
function getItemCount(items,propertyName)
{
var result = {};
for(var i = 0; i< items.length; i++) {
var groupKey = items[i][propertyName];
result[groupKey] = result[groupKey] ? result[groupKey] + 1 : 1;
}
return result;
}
How to apply the changes
Option 1:
Below is demonstrated probably one of easiest way how to apply those changes:
Open the page in Edit mode
Add Content Editor or Script Editor web part on the page
Insert the specified JavaScript template by enclosing it using
script tag into web part
Option 2:
Save the specified JavaScript template as a file (let's name it duplicatehighlight.js) and upload it into Site Assets library
Open the page in Edit mode and find JSLink property in List View web part
Specify the value: ~sitecollection/SiteAssets/duplicatehighlight.js and save the changes.
Result
SharePoint has some basic conditional formatting for Data View Web Parts and XSLT List Views, but the conditions you can use are rather limited. You can compare a field in the current item with a value that you specify. There are no formulas to count the number of items with the same name or similar, which would be the approach to use to identify duplicates.
If you need to identify duplicates, you may want to create a view that groups by the CNO number. Grouping will also include an item count, so you can run down the list and spot groups with more than one item.

Binding an edit box within a custom control to a form field programatically

I have a notes form with a series of fields such as city_1, city_2, city_3 etc.
I have an XPage and on that XPage I have a repeat.
The repeat is based on an array with ten values 1 - 10
var repArray = new Array() ;
for (var i=1;i<=10;i++) {
repArray.push(i) ;
}
return(repArray) ;
Within the repeat I have a custom control which is used to surface the fields city_1 through city_10
The repeat has a custom property docdatasource which is passed in
It also has a string custom property called cityFieldName which is computed using the repeat
collection name so that in the first repeat row it is city_1 and in the second it is city_2 etc..
The editable text field on the custom control is bound using the EL formula
compositeData.docdatasource[compositeData.cityFieldName]
This works fine but each time I add new fields I have to remember to create a new custom property and then a reference to it on the parent page.
I would like to be able to simply compute the data binding such as
compositeData.docdatasource['city_' + indexvar]
where indexvar is a variable representing the current row number.
Is this possible ? I have read that you cannot use '+' in Expression Language.
First: you wouldn't need an array for a counter. Just 10 would do (the number) - repeats 10 times too. But you could build an array of arrays:
var repArray = [];
for (var i=1;i<=10;i++) {
repArray.push(["city","street","zip","country","planet"]) ;
}
return repArray;
then you should be able to use
#{datasource.indexvar[0]}
to bind city,
#{datasource.indexvar[1]}
to bind street. etc.
Carries a little the danger of messing with the sequence of the array, if that's a concern you would need to dig deeper in using an Object here.
compute to javascript and use something like
var viewnam = "#{" + (compositeData.searchVar )+ "}"
return viewnam
make sure this is computed on page load in the custom control
I was never able to do the addition within EL but I have been very successful with simply computing the field names outside the custom control and then passing those values into the custom control.
I can send you some working code if you wish from a presentation I gave.

Creating an associative array using a while loop for select list?

I am dynamically generating a selectlist in Drupal and I want to create an associative array to populate the node ID as the value, and the title of the node as the option.
By default, it makes the value for each option the index of the select list. This is no good because the select list is dynamic, meaning the values won't be in the same order.
I used drupal_map_assoc to make the value the same as the option, but I have queries based on the value stored in this field, so if someone updates the value stored, the queries won't match.
<option value="Addison Reserve Country Club Inc.">Addison Reserve Country Club Inc.</option>
I want to replace the value with the Node ID also pulled with the query.
$sql = 'SELECT DISTINCT title, nid FROM {node} WHERE type = \'accounts\' ';
$result = db_query($sql);
while ($row = db_fetch_array($result)) {
$return[] = $row['title'];
//Trying to do something like 'Addison Reserve Country Club' => '2033' - where 2033 is the nid
}
$return = drupal_map_assoc($return);
I think you just want to do this inside the loop:
$return[$row['nid']] = $row['title'];
Based on your comment, you would also want to do an array_flip() right after the loop, but I think your comment may just have it backwards.

Resources