Use XPath in nodeset repeater (XForms) - html

I have a question about XPath and the nodeset repeater (XForms).
As you can see in the following code snippet I want to change an attribute of a specific entry of a list and additionally an attribute in the following entry in the nodeset with a trigger.
The first <xf:action> works fine but the second does not. What I want here is to leave the current nodeset of the processinstance, go to the following one and change the attribute state here. How do I realize that with XPath?
<div>
<xf:model>
<xf:instance xmlns="" id="template">
<project id="">
<name/>
...
<processinstance>
<name>
<state>
</processinstance>
</project>
</xf:instance>
</xf:model>
....
<!-- Process repeat table -->
<div>
<table class="table table-hover">
<thead>
<th width="50%">Processname</th>
<th width="50%">State</th>
<th width="50%">Action</th>
</thead>
<tbody id="process-repeat" xf:repeat-nodeset="//project[index('project-repeat')]/processinstance">
<tr>
<td>
<xf:output ref="name"/>
</td>
<td>
<xf:output ref="state"/>
</td>
<td>
<xf:group ref=".[state eq 'in processing']">
<xf:trigger appearance="minimal">
<xf:label>finish process</xf:label>
<xf:action>
<xf:setvalue ref="state">finished</xf:setvalue>
</xf:action>
<!-- THE FOLLOWING DOES NOT WORK AS I WANT! -->
<xf:action>
<xf:setvalue ref="//project[index('project-repeat')]/processinstance[index(process-repeat)+1]">in process</xf:setvalue>
</xf:action>
</xf:trigger>
</xf:group>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Best regards,
Felix

One thing is that you have a typo:
index(process-repeat)
vs.
index('process-repeat')
In addition, the index() function represents the currently selected, in the UI, repeat iteration. It does not represent the current iteration being evaluated in XPath.
The bottom line is that you cannot use index('process-repeat') to identify the current repeat iteration. It is a common misunderstanding of the index() function.
Some implementations have functions to identify the current repeat iteration. I assume you are using BetterFORM, and I don't know if it has such a function. With Orbeon Forms you could write:
//project[index('project-repeat')]/processinstance[xxf:repeat-position()]
Or better, if betterFORM supports variables, you could use that to avoid repeating yourself with:
<tbody id="process-repeat" xf:repeat-nodeset="//project[index('project-repeat')]/processinstance">
<xf:var name="current-process" value="."/>
<tr>
<td>
<xf:output ref="name"/>
</td>
<td>
<xf:output ref="state"/>
</td>
<td>
<xf:group ref=".[state eq 'in processing']">
<xf:trigger appearance="minimal">
<xf:label>finish process</xf:label>
<xf:action>
<xf:setvalue ref="state">finished</xf:setvalue>
</xf:action>
<xf:action>
<xf:setvalue ref="$current-process">in process</xf:setvalue>
</xf:action>
</xf:trigger>
</xf:group>
</td>
</tr>
</tbody>

Related

How to dynamically add HTML element/content - Angular

What would be the best way to dynamically add an HTML element, such as another column onto a basic HTML table?
I want to have a button below the table, and if the user were to click the button, the event would add the same amount of rows already in the table and add another column. I would want to support about 5 extra columns being added to the table.
Here's my HTML table as of right now:
<table>
<thead>
<tr>
<th id="row-tag"></th>
<th id="option-column">Option 1</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row-tag">P</td>
<td id="option-column">{{ p }}</td>
</tr>
<tr id="row-tag">
<td>
<app-a-p (saveButtonClick)="toggleAP($event)"
[modModalValues]="modModalValues">
</app-a-p>
</td>
<td id="option-column">
<div class="input-group input-group-sm">
$<input
*ngIf="toggleAP==true"
type="text"
name="aP"
size="10"
disabled
value=""
/>
<input
*ngIf="toggleAP==false"
type="text"
name="aP"
size="10"
[ngModel]="con.pA"
(ngModelChange)="con.pA = $event" appFormatP
(blur)="checkAP($event.target.value);
inputTracker.addModifiedValue('Option 1', $event.target.value)"
/>
</div>
</td>
</tr>
<tr>
<td id="row-tag">L</td>
<td id="option-column">${{l}}</td>
</tr>
<tr>
<td id="row-tag">R</td>
<td id="option-column">${{r}}</td>
</tr>
</tbody>
</table>
I think in Angular, you define table based on your data. for example, you have fields array defining columns, and data array defines the what's actually in the table.
<table >
<thead>
<tr>
<th *ngFor='let key of this.fields'>{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let row of this.data ' >
<td scope="row" *ngFor='let key of this.fields'> {{row[key]}} </td>
</tr>
</tbody>
</table>
when you need a new column, just push a new field into fields. like
fields.push('newcolumn');
when you need a new row, just do:
data.push({col1: '', col2:'', newcolumn: ''});
Look into the insertRow() and insertCell() functions in JavaScript. This alongside an onClick function that you write will let you edit the table.
A good way of generating a table on UI when using angular would be to use 2D-array (row*column) use can have a button using which you can dynamically add values to this array and have another row/column to the table.

Scraping HTML by Class in VBA

I have a html code as shown
<div class="property-title visible-xs">
<a href="/property/473902/Office-Lot">
<h2><b> 2nd Floor, Block D5, Solaris Dutamas, No. 1, Jalan Dutamas 1, 50480, Kuala Lumpur</b></h2>
</a>
</div>
<p style="color: #0071ee;">Office Lot</p>
<h4><b>RM 880,000</b></h4>
<div>
<table>
<!-- <tr><td>Office Lot</td></tr> -->
<tr>
<td>Property Code</td><td>:</td><td>PB473902</td>
</tr>
<tr>
<td>Auction Date</td><td>:</td><td>2016-02-26</td>
</tr>
<tr>
<td>Built up </td><td>:</td><td>754 sq.ft </td>
</tr>
<tr>
<td>Tenure</td><td>:</td><td>Freehold</td>
</tr>
and I used the following code to extract the details "2nd Floor, Block D5,...."
objIE1.Document.getElementsByClassName("property-title visible-xs").getElementsByTagName ("a")
but it don't seem to get the result I need. Please help.
The html code shown is in multiple form.
This will work:
extract1 = objIE1.Document.getElementsByClassName("property-title visible-xs")(0).getElementsByTagName ("a")(0).innerText
Cells(1,1).Value = extract1
When a function has getElementsBy (plural - "Elements") such as getElementsByClassName or getElementsByTagName the code will extract a collection of elements so you need to specify which one you want, in this case it is the first which in html is 0. When a function uses getElementBy (singular - "Element") such as getElementById this extracts a single element and therefore does not need an index specification as there is no collection.

AngularJS seems to be working but ng-repeat is not

I'm stumped and can't find the bug.
Angular is working, because it's reading my {{expressions}}, however, it's not replacing them with the content I'm expecting. It's simply removing them and blanks sit in their place.
I'm sure this issue is also tied in with, for some reason, my ng-repeat directive isn't working. (It's not repeating.)
Can someone help me out? I'm trying to draw a table. In this example, when it's done, it should have the respective "idea" posted multiple times across the same row, and each row should have a different "idea", as listed in the $scope.
It's creating one single row filled with blanks (rather than {{idea}} ).
index.html
<!doctype html>
<html ng-app="AppName">
<head>
<link rel="stylesheet" type="text/css" href="styles/table.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
</head>
<body>
<div ng-controller="TableController">
<table>
<tr>
<td>
<table cellspacing="0">
<tr class="title_bar">
<td>Title</td>
<td>Rating</td>
<td>Votes</td>
<td>Comments</td>
<td>Post Date</td>
<td>Status</td>
</tr>
</table>
</td>
</tr>
<div ng-repeat="idea in ideas">
<tr style="color: white">
<td>{{idea}}</td>
<td>{{idea}}%</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
</tr>
</div>
</table>
</div>
<script src="scripts/controllers/TableController.js"></script>
</body>
</html>
TableController.js
var app = angular.module('AppName', []);
app.controller('TableController', ['$scope',function($scope){
$scope.ideas = [
'wow',
'cool',
'so nice',
'amazing',
'please work'
];
}]);
I'm probably missing something obvious but I appreciate any help you could give me.
Edit: Whoops, guess I need to brush up on my HTML basics.
Well, your HTML layout looks pretty strange. You shouldn't put <div> between <tr>
Try something like this:
<table>
<tr class="title_bar">
<td>Title</td>
<td>Rating</td>
<td>Votes</td>
<td>Comments</td>
<td>Post Date</td>
<td>Status</td>
</tr>
<tr ng-repeat="idea in ideas">
<td>{{idea}}</td>
<td>{{idea}}%</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
<td>{{idea}}</td>
</tr>
</table>
Fiddle demo
What you have is invalid HTML, so it's not rendering how you expect it to. You can't put a <div> inside a <table> and have it contain elements; you can include a <div> inside a <td> element but that doesn't really help you.
If you want to use ng-repeat in a table use it in <tr> or <tbody>
<tr ng-repeat="idea in ideas">
<td>{{idea}}</td>
........
</tr>
Try adding the ng-repeat directive to the td itself.
<tr>
<td ng-repeat="idea in ideas">{{idea}}</td>
</tr>
That should iterate through your $scope.ideas array.

How can i determine first row of html table using angular?

I can think of a few hacky ways, but for example below in my doSomething method, how can i determine the rowIndex?
<tr ng-repeat="a in mydata">
<td><b>{{doSomething(mydata.name)}}</b></td>
<td>{{age}}</td>
<td>hello</td>
</tr>
ng-repeat provides properties $first, $index, $middle, and $last. Since in the title question you asked about the first row, you could pass $first as a boolean:
<tr ng-repeat="a in mydata">
<td><b>{{doSomething($first)}}</b></td>
<td>{{a.age}}</td>
<td>hello</td>
</tr>
AngularJS automatically includes the magic $index in an ng-repeat. So you can get the row number like so:
<tr ng-repeat="a in mydata">
<td><b>{{doSomething($index)}}</b></td>
<td>{{a.name}}</td>
<td>{{a.age}}</td>
</tr>

MVC Razor View Engine, add logic between quotemarks

I'm really new at using Razor with MVC, and so far I really like it.
One little thing I want to do is write a variables value to an attribute in HTML.
For example, if I had the following:
<table style="width: 100%">
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Value
</th>
</tr>
#foreach (var item in Model)
{
<tr id="ID#item.id">
<td>
#item.id
</td>
<td>
#item.name
</td>
<td>
#item.value
</td>
<td>
</tr>
}
</table>
I would want all the tags to have an ID equal to "ID[insert item's id]", but instead I get an ID equal to "ID#item.id".
How do I write a variable's name between HTML quote marks?
Thanks!
This pattern is recognized as an email address. Do the following to work around this behavior:
<tr id="ID#(item.id)">