AngularJS seems to be working but ng-repeat is not - html

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.

Related

I can't get value in Thymeleaf template th:each

Java code
int[] days = {Integer.valueOf(tokens[2])};
model.addAttribute("days", days);
HTML code
<tr th:each="day : ${days}">
<p th:text="${day}"></p>
<p th:text="${dayStat.index}"></p>
<tr>
<td th:text="${day}"></td>
</tr>
</tr>
browser page source code
<tr>
<p>28</p>
<p>0</p>
<tr>
<td></td>
</tr>
<tr>
If I access through th:each in Thymeleaf, I can access right below.
However, if you go deeper into other tags, you cannot get the value.
I do not know why.
Can you tell me?
I expected:
browser page source code
<tr>
<p>28</p>
<p>0</p>
<tr>
<td>28</td>
</tr>
<tr>

Use XPath in nodeset repeater (XForms)

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>

Create a table in thymeleaf

I'm new to thymeleaf and am trying to make a simple table using an array and an each loop.
My code looks like this:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Smoke Tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<table border="1" style="width:300px">
<tr>
<td>Test Name</td>
</tr>
<tr th:each="smokeTest : ${smokeTests}">
<td>
th:text="${smokeTest.name}">A Smoke Test'
</td>
</tr>
</table>
</body>
</html>
Basically my problem is that I can't run the loop as <td>s within <tr>s. Is there any way that this code could work?
You must put th:text as an attribute of a tag, so
<tr th:each="smokeTest : ${smokeTests}">
<td th:text="${smokeTest.name}">A Smoke Test'</td>
</tr>
should run.
Simple solution which comes to mind first:
<th:block th:each="smokeTest : ${smokeTests}">
<tr>
<td th:text="${smokeTest.name}">A Smoke Test'</td>
</tr>
</th:block>
Details: http://www.thymeleaf.org/whatsnew21.html#bloc
Although, it's late answer.
It's work more specifically, like
<tr th:each="smokeTest : ${smokeTests}">
<td><p th:text="${smokeTest.name}"></p></td>
</tr>

Repeating an HTML snippet that contains elements with id attribute defined

I need to repeat an html snippet several times on a page but the problem is that the contained html elements have id defined that should be unique on page. So what is the proper way I could repeat this snippet without removing the id attribute from the elements ?
Could I use iframe as container for this snippet & let the duplicate ids exist on page?
You can use JavaScript to clone the snippet and at the same time change the IDs.
Example if your snippet is:
<div id="snippet">
<table id="list">
<tr id="0">
<td id="firstName0">John</td>
<td id="lastName0">Smith</td>
</tr>
<tr id="1">
<td id="firstName2">John</td>
<td id="lastName2">Doe</td>
</tr>
</table>
</div>
Using
$("#snippet").clone(false).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + "_1"); });
Will Produce
<div id="snippet_1">
<table id="list_1">
<tr id="0_1">
<td id="firstName0_1">John</td>
<td id="lastName0_1">Smith</td>
</tr>
<tr id="1_1">
<td id="firstName2_1">John</td>
<td id="lastName2_1">Doe</td>
</tr>
</table>
</div>
Which will solve the duplicate ID problem.

Nokogiri XML to node

I'm reading a local HTML document with Nokogiri like so:
f = File.open(local_xml)
#doc = Nokogiri::XML(f)
f.close
#doc contains a Nokogiri XML object that I can parse using at_css.
I want to modify it using Nokogiri's XML::Node, and I'm absolutely stuck. How do I take this Nokogiri XML document and work with it using node methods?
For example:
#doc.at_css('rates tr').add_next_sibling(element)
returns:
undefined method `add_next_sibling' for nil:NilClass (NoMethodError)
despite the fact that #doc.class is Nokogiri::XML::Document.
For completeness, here is the markup I'm trying to edit.
<html>
<head>
<title>Exchange Rates</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<table class="rates">
<tr>
<td class="up"><div></div></td>
<td class="date">Saturday, Jan 12</td>
<td class="rate up">3.83</td>
</tr>
<tr>
<td class="up"><div></div></td>
<td class="date">Friday, Jan 11</td>
<td class="rate up">3.70</td>
</tr>
<tr>
<td class="down"><div></div></td>
<td class="date">Thursday, Jan 10</td>
<td class="rate down">3.68</td>
</tr>
<tr>
<td class="down"><div></div></td>
<td class="date">Wedensday, Jan 9</td>
<td class="rate down">3.70</td>
</tr>
<tr>
<td class="up"><div></div></td>
<td class="date">Tuesday, Jan 8</td>
<td class="rate up">3.66</td>
</tr>
</table>
</body>
</html>
This is an example how to do what you are trying to do. Starting with f containing a shortened version of the HTML you want to parse:
require 'nokogiri'
f = '
<html>
<head>
<title>Exchange Rates</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<table class="rates">
<tr>
<td class="up"><div></div></td>
<td class="date">Saturday, Jan 12</td>
<td class="rate up">3.83</td>
</tr>
</table>
</body>
</html>
'
doc = Nokogiri::HTML(f)
doc.at('.rates tr').add_next_sibling('<p>foobar</p>')
puts doc.to_html
Your code is incorrectly trying to find the class="rates" parameter for <table>. In CSS we'd use .rates. An alternate way to do it using CSS is table[class="rates"].
Your example didn't define the node you were trying to add to the HTML, so I appended <p>foobar</p>. Nokogiri will let you build a node from scratch and append it, or use markup and add that, or you could find a node from one place in the HTML, remove it, and then insert it somewhere else.
That code outputs:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Exchange Rates</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<table class="rates">
<tr>
<td class="up"><div></div></td>
<td class="date">Saturday, Jan 12</td>
<td class="rate up">3.83</td>
</tr>
<p>foobar</p>
</table>
</body>
</html>
It's not necessary to use at_css or at_xpath instead of at. Nokogiri senses what type of accessor you're using and handles it. The same applies using xpath or css instead of search. Also, at is equivalent to search('some accessor').first, so it finds the first occurrence of the matching node.
Try to load as HTML instead of XML Nokogiri::HTML(f)
Not getting in much detail on how Nokogiri works, lets say that XML does not have css right? So the method at_css doesn't make sense (maybe it does I dunno). So it should work loading as Html.
Update
Just noticed one thing. You want to do at_css('.rates tr') insteand of at_css('rates tr') because that's how you select a class in css. Maybe it works with XML now.