How to iterate Guava multimap in thymleaf - thymeleaf

I have below map collection. I want to iterate this in thymeleaf but getting below error.
Multimap<String,String> map = ArrayListMultimap.create();
<div th:each="m : ${menu.entries}">
EL1008E: Property or field 'entries' cannot be found on object of type 'com.google.common.collect.ArrayListMultimap' - maybe not public or not valid?

Here is one way of iterating a Guava multimap in Thymeleaf.
Some test data:
Multimap<String, String> map = ArrayListMultimap.create();
map.put("key one", "value one");
map.put("key two", "value two a");
map.put("key two", "value two b");
map.put("key three", "value three");
The Thymeleaf:
<div th:each="k : ${menu.keySet()}">
<div th:text="'key is: ' + ${k}">
</div>
<div th:each="v : ${menu.get(k)}">
<div th:text="'val is: ' + ${v}">
</div>
</div>
</div>
This gives the following output in the web page (ordering is not guaranteed):
key is: key two
val is: value two a
val is: value two b
key is: key one
val is: value one
key is: key three
val is: value three

Related

ASP.NET MVC 5 always display the first row in the table [duplicate]

this is a tricky one to explain, so I'll try bullet pointing.
Issue:
Dynamic rows (collection) available to user on View (add/delete)
User deletes row and saves (POST)
Collection passed back to controller with non-sequential indices
Stepping through code, everything looks fine, collection items, indices etc.
Once the page is rendered, items are not displaying correctly - They are all out by 1 and therefore duplicating the top item at the new 0 location.
What I've found:
This happens ONLY when using the HTML Helpers in Razor code.
If I use the traditional <input> elements (not ideal), it works fine.
Question:
Has anyone ever run into this issue before? Or does anyone know why this is happening, or what I'm doing wrong?
Please check out my code below and thanks for checking my question!
Controller:
[HttpGet]
public ActionResult Index()
{
List<Car> cars = new List<Car>
{
new Car { ID = 1, Make = "BMW 1", Model = "325" },
new Car { ID = 2, Make = "Land Rover 2", Model = "Range Rover" },
new Car { ID = 3, Make = "Audi 3", Model = "A3" },
new Car { ID = 4, Make = "Honda 4", Model = "Civic" }
};
CarModel model = new CarModel();
model.Cars = cars;
return View(model);
}
[HttpPost]
public ActionResult Index(CarModel model)
{
// This is for debugging purposes only
List<Car> savedCars = model.Cars;
return View(model);
}
Index.cshtml:
As you can see, I have "Make" and "Actual Make" inputs. One being a HTML Helper and the other a traditional HTML Input, respectively.
#using (Html.BeginForm())
{
<div class="col-md-4">
#for (int i = 0; i < Model.Cars.Count; i++)
{
<div id="car-row-#i" class="form-group row">
<br />
<hr />
<label class="control-label">Make (#i)</label>
#Html.TextBoxFor(m => m.Cars[i].Make, new { #id = "car-make-" + i, #class = "form-control" })
<label class="control-label">Actual Make</label>
<input class="form-control" id="car-make-#i" name="Cars[#i].Make" type="text" value="#Model.Cars[i].Make" />
<div>
<input type="hidden" name="Cars.Index" value="#i" />
</div>
<br />
<button id="delete-btn-#i" type="button" class="btn btn-sm btn-danger" onclick="DeleteCarRow(#i)">Delete Entry</button>
</div>
}
<div class="form-group">
<input type="submit" class="btn btn-sm btn-success" value="Submit" />
</div>
</div>
}
Javascript Delete Function
function DeleteCarRow(id) {
$("#car-row-" + id).remove();
}
What's happening in the UI:
Step 1 (delete row)
Step 2 (Submit form)
Step 3 (results)
The reason for this behavior is that the HtmlHelper methods use the value from ModelState (if one exists) to set the value attribute rather that the actual model value. The reason for this behavior is explained in the answer to TextBoxFor displaying initial value, not the value updated from code.
In your case, when you submit, the following values are added to ModelState
Cars[1].Make: Land Rover 2
Cars[2].Make: Audi 3
Cars[3].Make: Honda 4
Note that there is no value for Cars[0].Make because you deleted the first item in the view.
When you return the view, the collection now contains
Cars[0].Make: Land Rover 2
Cars[1].Make: Audi 3
Cars[2].Make: Honda 4
So in the first iteration of the loop, the TextBoxFor() method checks ModelState for a match, does not find one, and generates value="Land Rover 2" (i.e. the model value) and your manual input also reads the model value and sets value="Land Rover 2"
In the second iteration, the TextBoxFor() does find a match for Cars[1]Make in ModelState so it sets value="Land Rover 2" and manual inputs reads the model value and sets value="Audi 3".
I'm assuming this question is just to explain the behavior (in reality, you would save the data and then redirect to the GET method to display the new list), but you can generate the correct output when you return the view by calling ModelState.Clear() which will clear all ModelState values so that the TextBoxFor() generates the value attribute based on the model value.
Side note:You view contains a lot of bad practice, including polluting your markup with behavior (use Unobtrusive JavaScript), creating label element that do not behave as labels (clicking on them will not set focus to the associated control), unnecessary use of <br/> elements (use css to style your elements with margins etc) and unnecessary use of new { #id = "car-make-" + i }. The code in your loop can be
#for (int i = 0; i < Model.Cars.Count; i++)
{
<div class="form-group row">
<hr />
#Html.LabelFor(m => m.Cars[i].Make, "Make (#i)")
#Html.TextBoxFor(m => m.Cars[i].Make, new { #class = "form-control" })
....
<input type="hidden" name="Cars.Index" value="#i" />
<button type="button" class="btn btn-sm btn-danger delete">Delete Entry</button>
</div>
}
$('.delete').click(function() {
$(this).closest('.form-group').remove();
}

TextBoxFor displaying the wrong name? [duplicate]

this is a tricky one to explain, so I'll try bullet pointing.
Issue:
Dynamic rows (collection) available to user on View (add/delete)
User deletes row and saves (POST)
Collection passed back to controller with non-sequential indices
Stepping through code, everything looks fine, collection items, indices etc.
Once the page is rendered, items are not displaying correctly - They are all out by 1 and therefore duplicating the top item at the new 0 location.
What I've found:
This happens ONLY when using the HTML Helpers in Razor code.
If I use the traditional <input> elements (not ideal), it works fine.
Question:
Has anyone ever run into this issue before? Or does anyone know why this is happening, or what I'm doing wrong?
Please check out my code below and thanks for checking my question!
Controller:
[HttpGet]
public ActionResult Index()
{
List<Car> cars = new List<Car>
{
new Car { ID = 1, Make = "BMW 1", Model = "325" },
new Car { ID = 2, Make = "Land Rover 2", Model = "Range Rover" },
new Car { ID = 3, Make = "Audi 3", Model = "A3" },
new Car { ID = 4, Make = "Honda 4", Model = "Civic" }
};
CarModel model = new CarModel();
model.Cars = cars;
return View(model);
}
[HttpPost]
public ActionResult Index(CarModel model)
{
// This is for debugging purposes only
List<Car> savedCars = model.Cars;
return View(model);
}
Index.cshtml:
As you can see, I have "Make" and "Actual Make" inputs. One being a HTML Helper and the other a traditional HTML Input, respectively.
#using (Html.BeginForm())
{
<div class="col-md-4">
#for (int i = 0; i < Model.Cars.Count; i++)
{
<div id="car-row-#i" class="form-group row">
<br />
<hr />
<label class="control-label">Make (#i)</label>
#Html.TextBoxFor(m => m.Cars[i].Make, new { #id = "car-make-" + i, #class = "form-control" })
<label class="control-label">Actual Make</label>
<input class="form-control" id="car-make-#i" name="Cars[#i].Make" type="text" value="#Model.Cars[i].Make" />
<div>
<input type="hidden" name="Cars.Index" value="#i" />
</div>
<br />
<button id="delete-btn-#i" type="button" class="btn btn-sm btn-danger" onclick="DeleteCarRow(#i)">Delete Entry</button>
</div>
}
<div class="form-group">
<input type="submit" class="btn btn-sm btn-success" value="Submit" />
</div>
</div>
}
Javascript Delete Function
function DeleteCarRow(id) {
$("#car-row-" + id).remove();
}
What's happening in the UI:
Step 1 (delete row)
Step 2 (Submit form)
Step 3 (results)
The reason for this behavior is that the HtmlHelper methods use the value from ModelState (if one exists) to set the value attribute rather that the actual model value. The reason for this behavior is explained in the answer to TextBoxFor displaying initial value, not the value updated from code.
In your case, when you submit, the following values are added to ModelState
Cars[1].Make: Land Rover 2
Cars[2].Make: Audi 3
Cars[3].Make: Honda 4
Note that there is no value for Cars[0].Make because you deleted the first item in the view.
When you return the view, the collection now contains
Cars[0].Make: Land Rover 2
Cars[1].Make: Audi 3
Cars[2].Make: Honda 4
So in the first iteration of the loop, the TextBoxFor() method checks ModelState for a match, does not find one, and generates value="Land Rover 2" (i.e. the model value) and your manual input also reads the model value and sets value="Land Rover 2"
In the second iteration, the TextBoxFor() does find a match for Cars[1]Make in ModelState so it sets value="Land Rover 2" and manual inputs reads the model value and sets value="Audi 3".
I'm assuming this question is just to explain the behavior (in reality, you would save the data and then redirect to the GET method to display the new list), but you can generate the correct output when you return the view by calling ModelState.Clear() which will clear all ModelState values so that the TextBoxFor() generates the value attribute based on the model value.
Side note:You view contains a lot of bad practice, including polluting your markup with behavior (use Unobtrusive JavaScript), creating label element that do not behave as labels (clicking on them will not set focus to the associated control), unnecessary use of <br/> elements (use css to style your elements with margins etc) and unnecessary use of new { #id = "car-make-" + i }. The code in your loop can be
#for (int i = 0; i < Model.Cars.Count; i++)
{
<div class="form-group row">
<hr />
#Html.LabelFor(m => m.Cars[i].Make, "Make (#i)")
#Html.TextBoxFor(m => m.Cars[i].Make, new { #class = "form-control" })
....
<input type="hidden" name="Cars.Index" value="#i" />
<button type="button" class="btn btn-sm btn-danger delete">Delete Entry</button>
</div>
}
$('.delete').click(function() {
$(this).closest('.form-group').remove();
}

What does '...' in React-Native mean?

A piece of react-native code:
enderScene(route, navigator) {
let Component = route.component;
return (
<Component {...route.params} navigator={navigator}></Component>
);
}
this code returns a Component Object ,
But I don't understand this code ---> {...route.params}
Question:
What is meant by '...' ?
Can you tell me what is meant by " {...route.params}" ?
The '...' is called Spread syntax.
The spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected.
Example :
var car = ["door", "motor", "wheels"];
var truck = [...car, "something", "biggerthancar"];
// truck = ["door", "motor", "wheels", "something", "biggerthancar"]
If you want to know more about spread operator :
https://rainsoft.io/how-three-dots-changed-javascript/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
To expand on the above, in the context of the original post the spread operator is essentially passing through all of the parameters in route.params
For example if route.params was the object
{key: 'my-route', title: 'My Route Title'}
Then
<Component {...route.params} navigator={navigator} />
Could be re-written as
<Component key={route.params.key} title={route.params.title} navigator={navigator} />
The other "side" of this is the destructuring assignment (example using stateless react components)
const Component = (props) => {
// this is simply referencing the property by the object key
let myKey = props.key
// this is using destructuring and results in the variables key, title and navigator which are from props.key, props.title and props.navigator
let { key, title, navigator } = props
return <Text>{title}</Text>
}
You can also do this in the function declaration like so which achieves the same thing
const Component = ({key, title, navigator}) => {
// now you have variables key, title and navigator
return <Text>{title}</Text>
}
See Destructuring
Ok, I was confused about that for a long period of time.
So, I'll try my best to explain it to you:
Suppose, you've a react class like bellow:
import React, {Component} from 'react';
import { Link } from 'react-router-dom';
class SingleService extends Component{
render(){
return(
<div class="col-md-4">
<span class="fa-stack fa-4x">
<i class="fas fa-circle fa-stack-2x text-primary"></i>
<i class={`fas ${this.props.icon} fa-stack-1x fa-inverse`}></i>
</span>
<h4 class="service-heading">{this.props.title}</h4>
<p class="text-muted">{this.props.description}</p>
</div>
);
}
}
export default SingleService;
Here, you can see that there are so many {this.props.variable}.
Those are used to create dynamic values when we import this above class into another class, like bellow:
import React, {Component} from 'react';
import { Link } from 'react-router-dom';
import SingleService from './SingleService';
// declaring a constant array to hold all of our services props.
// The following array is made up of the objects.
const services = [
{
title:'E-commerce',
description:'Description text on E-commerce',
icon: 'fa-shopping-cart'
}
];
class Services extends Component{
render(){
return(
<div>
<section class="page-section" id="services">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2 class="section-heading text-uppercase">Services</h2>
<h3 class="section-subheading text-muted">Lorem ipsum dolor sit amet consectetur.</h3>
</div>
</div>
<div class="row text-center">
{/* it's looping through an object, that's why we've used key value pair. */}
{ /*
to write js inside JSX, we use curly braces
here we're using array.map() function.
*/}
{services.map((service, index) => {
// returning our component with props.
// return (<SingleService title={service.title} description={service.description} icon={service.icon} />);
// or, we can write the following
return (<SingleService {...service}/>);
})}
</div>
</div>
</section>
</div>
);
}
}
export default Services;
Now, here, I've used the famous
return (<SingleService {...SingleService}/>);
But one very important thing, I could avoid using it simply by writing the following line:
return (<SingleService title={service.title} description={service.description} icon={service.icon} />);
So, you can see in the send return statement, I've specified all of the props variables individually and assigned values to those, whereas in the first return statement, I've passed in all pf the props together from the SingleService object at once, that will pass all od the key-value pairs.
To add to the above given answers, the ... or the spread operator is not something special to react native. It is a feature in es6. ES6 stands for ecma script and is the standard followed for javascript. This means that you could create a .js file outside of react/react-native and run it in a node env and the spread operator would still work.

How to pass dropdown list selected value in knockout function?

I have to pass the dropdown selected value in knockout function. I have crated the razor syntax for that:
<div class="row">
#Html.LabelFor(m => m.FilterByType, htmlAttributes: new { #class = "label" })
#Html.DropDownListFor(m => m.FilterByType, new SelectList(Model.aspNetUser, "FilterByType", "FilterByName"), new { #class = "selectBox", #id = "aspnetUsersType", #data_bind = "event: {change: getData(0,'','',size,index,'')}" })
<input type="hidden" id="filterByType" name="filterByType" value="">
</div>
Following is my knockout function:
self.getData = function (filterbytype, fromdaterange, todaterange, pageSize, page, searchText) {"some task"}
How do I pass the selected value in the getData? Right now I am passing 0 as a filterbytype.
The objects can be passed from server to client using JSON, and binded to a property of type observableArray. Then bind this property to a html element using foreach binding. You can see an example here:
http://knockoutjs.com/documentation/foreach-binding.html
Suppose are using this following code in ur HTML
<select data-bind="options: operations, value: self.selectedOperation">
Make sure that You must be using these variables as ko.observable() type
so ur JS code will look like this
var self = this;
self.selectedOperation = ko.observable("Option1"); // with self u can use more variables and here selectedOperation will be containing the choosen value you want and you can pass it wherever u want
var operations = ko.observableArray(["Option1", "Option2", "option3", "Opt4"]); // dropdown List
Now its up to you how you are going to use that variable..

Grails Dynamic radio group

I have a requirement for a grails application to display a list of questions on the screen with 6 grade options listed below each of the questions. The information for these questions and grades is coming from a lookup table in the database. I have the questions and grades displaying on the screen but I'm not sure how to go about getting the lookup information to save in the database. I would also like to know if there is a way to have a certain grade selected by default for each of the questions. I tried the checked="S" but this only selects the S grade for the very bottom questions.
My code for the view is
<label for="questions"></label>
<ul class="one-to-many">
<!-- Evaluation Questions -->
<g:each in="${cdeEvaluationInstance?.questions}" var="evalQuestion" status="i">
<g:hiddenField name="cdeEvaluation.questions[${i}].id" value="${evalQuestion.id}"/>
<legend>
${evalQuestion.areaOfEval.title}
</legend>
<p>
<strong>Focus areas: ${evalQuestion.areaOfEval.focusArea}</strong>
</p>
<p>
<em> ${evalQuestion.areaOfEval.description}
</em>
</p>
<p>
<g:each in="${evalQuestion.areaOfEval.grades.sort{it.grade}}"
var="grade" ><div class="radio">
<span class="clear long">
<input type="radio"
name="radioGroup" value="${evalQuestion.grade}" checked="S" />
<label class="long"><strong> ${grade.grade}
</strong> ${grade.description}</label>
</div>
</g:each>
My code for the controller is
def evalQuestions = EvaluationService.fetchActiveEvaluationQuestions();
//def evaluation = new CdeEvaluation(questions: evalQuestions)
def evaluation = new CdeEvaluation(params)
evaluation.setQuestions(evalQuestions)
My domain for the table that the questions and answers are
package gov.mt.mdt.cde.domain.evaluation
import java.util.Date;
class CdeEvalQuestion extends Base{
CdeAreaOfEvaluation areaOfEval
CdeAreaOfEvalCriteria grade
String comments
static belongsTo = [cdeEvaluation: CdeEvaluation]
static mapping = {
id column: 'cevqu_id_seq'
id generator: 'sequence', params: [sequence: 'cevqu_id_seq']
areaOfEval column: 'caoe_id_seq'
grade column: 'caoec_id_seq'
}
static constraints = {
comments(blank:true, nullable:true, maxSize:2000)
createdBy(blank: false, nullable:false, maxSize:13)
dateCreated(blank: false, nullable:false)
lastUpdatedBy(blank: false, nullable:true, maxSize:13)
lastUpdated(blank: false, nullable:true)
}
}
I am just starting to learn grails/groovy so any help or examples you could point me to would be great. Thanks!
So selecting a particular question by default you would do something like:
<g:radioGroup name="myGroup" labels="evalQuestion.areaOfEval.grades" values="evalQuestion.areaOfEval.grades*.grade" value="evalQuestion.grade">
${it.radio} <label class="long"><strong>${it.label.grade}</strong> ${it.label.description}</label>
</g:radioGroup>
That doesn't require you write the inner each. Basically you pass an array of labels and a parallel array of values. The value attribute is the default value from the values attribute. The inner body of the radioGroup will be repeated for each label and value pair. The *. (aka spread operator) basically is the same thing as using the collect() method.
I removed the spread operator for label and I passed the full object in for the label. Then inside the body of the tag when I do it.label I have the full object and can use different fields it.label.description and it.label.grade.
As for setting the default to grade S. You'll need to write the code to find grade S from evalQuestion.areaOfEval.grades. Something like:
evalQuestion.areaOfEval.grades.find { it.grade == 'S' }
And pass that to value attribute of the tag. You could do this:
<g:set var="defaultGrade" value="evalQuestion.areaOfEval.grades.find { it.grade == 'S' }"/>
<g:radioGroup name="myGroup"
labels="evalQuestion.areaOfEval.grades"
values="evalQuestion.areaOfEval.grades*.grade"
value="defaultGrade">

Resources