how to create communication with dynamic text box [closed] - zk

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
How to communicate between dynamic textbox that without id .
In normal case we can have some of the event name onchange and etc . but in dynamic component. We don't have that key (id) to link it. Like onchange$id then do something "".
so in dynamic component case , how to get value from dynamic component? Please provide idea.

since your question isn't very precise (about how you create those components dynamicall - java or zul templates) here the 2 basic methods:
from java code:
after creating a new component just add an event listener programmatically, no need for any convention based method names.
//create dynamically anywhere
Textbox someInput = new Textbox();
someInput.setParent(someParent);
someInput.addEventListener(Events.ON_CHANGE, this::onChangeSomeInput);
//someInput.addEventListener(Events.ON_CHANGE, (InputEvent event) -> {...});
...
public void onChangeSomeInput(InputEvent event) {
Textbox someInput = event.getTarget();
someInput.getValue();
}
from zul code:
in this case event forwarding is the tool of choice, it lets you delegate the event to a parent component with an id
<grid id="mygrid">
<template name="model">
<row>
<textbox forward="onChange=mygrid.onChangeSomeInput(${each})"/>
</row>
</template>
</grid>
then you can implement a composer method like this
public void onChangeSomeInput$mygrid(ForwardEvent forwardEvent) {
InputEvent event = (InputEvent)forwardEvent.getOrigin();
Object each = forwardEvent.getData();
}
(I wrote this code our of my head so please excuse typos/errors, I'll be happy to provide running examples in case you specify your question)

Related

Thymeleaf form with multiple objects of the same class

Simple problem but can't find a solution: I have a Thymeleaf form used to add a new object, say of a Book class. It works perfectly well and I only need that particular form for adding new objects, not editing the existing ones. The question is: how can I put several objects of the Book class in the same single form? So, purely for convenience, instead of filling form for a single book and clicking Send you can fill form for several books at once and only then click Send, have them all inserted into the database (in whatever order) and also have the option to fill the form partially (e.g. the form has room for 5 books but it will also accept 1, 2, 3 or 4 and you can leave the rest blank).
Edit: I've tried passing a list of object to the Thymeleaf template with the form bound to the whole list and iteration inside, but Thymeleaf throws BingingResultError upon rendering it.
You need to use a wrapper object to realize what you want.
Something like:
public class BooksCreationDto {
private List<Book> books;
// default and parameterized constructor
public void addBook(Book book) {
this.books.add(book);
}
// getter and setter
}
Then you need to pass this object as a model attribute in your controller:
BooksCreationDto booksForm = new BooksCreationDto();
model.addAttribute("form", booksForm);
bind fields using index property
th:field="*{books[__${itemStat.index}__].title}"
and get back the result with
#ModelAttribute BooksCreationDto form
in your controller.
For a complete and detailled explaination visit: https://www.baeldung.com/thymeleaf-list

OOTB Granite Render Condition in AEM [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have created a button called annotation and I have added hasannotation OOTB granite render condition. On selection of an image having annotation, the button doesn't get rendered.
Image Of the custom button with granite:rendercondition
Properties of the button
Properties of granite:rendercondition node
First you need to add granite:rel property to your button.
As said in the documentation:
This is used to indicate the semantic relationship of the component
similar to HTML rel attribute.
You can add the AEM existing granite:rel in your custom button as "aem-assets-admin-actions-annotate-activator" as shown /libs/dam/gui/content/assets/jcr:content/actions/selection/annotate
Or you can also add your custom value lets say "my-annotation-rel". In this case you need to tell AEM to consider your custom value. In order to do this, you need to overlay /libs/dam/gui/coral/components/admin/contentrenderer/base/assetBase.jsp
and add this line :
actionRels.add("my-annotation-rel");
Update: render condition is not working because the path is not correctly passed to redercondition component. {requestPathInfo.suffix} does not give the actual path of the asset rather it gives the folder path and hence it fails to check when you are in card/column/list view.
In order to implement this, follow these steps:
Overlay /libs/dam/gui/coral/components/admin/contentrenderer/base/base.jsp
Add this below code inside getActionRels(Node node, boolean hasReplicate,boolean hasRemoveNode, boolean hasModifyAccessControl, boolean isExpiredAsset, boolean isExpiredSubAsset, boolean isDAMAdmin, boolean isContentFragment) method
boolean hasAnnotation = false;
NodeIterator nodeItr= node.getNodes();
Node commentsNode;
while(nodeItr.hasNext()) {
Node childNode = nodeItr.nextNode();
NodeIterator childItr = childNode.getNodes();
while(childItr.hasNext()) {
Node secondLevelChild = childItr.nextNode();
if(secondLevelChild.getName().equals("comments")) {
NodeIterator thirdLevelNode = secondLevelChild.getNodes();
while(thirdLevelNode.hasNext()){
if(thirdLevelNode.nextNode().hasProperty("annotationData")){
hasAnnotation = true;
}
}
}
}
}
if(hasAnnotation){
actionRels.add("my-annotation-rel");
}
Add granite:rel (String) "my-annotation-rel" property to your custom button
It should work.
Another way without changing the OOTB jsp file behaviour, if you are customising metadataeditor then granite render condition should work . In this case you have to first overlay this and your custom button:
/libs/dam/gui/content/assets/metadataeditor/jcr:content/actions
and add granite:rendercondition node under your custom button and give path property as
${empty requestPathInfo.suffix ? param.item : requestPathInfo.suffix}

Play Framework Html class and Form Rendering without Input

I have 2 questions. Version 2.4.x of the Play! Framework.
Whenever I render a layout using layoutName.render(inputargs...); it returns an "Html" object. I have not found a reference to this class in any of the docs. Where do I find this class? This doesn't seem to yield anything. (Edit2: Found in play.twirl.api.Html)
I am rendering a search bar on every page which is created using an input form. The problem is that the main layout needs my model class for the form as an argument: mainLayout.render("title", something_else, new Form<Search>()); Is there any way of writing it as mainLayout.render("title", something_else); whilst still retaining the form?
Edit3: Apparently the form is not needed at all; so long the name of the input is the same as the model's name any form will work:
#helper.form(action = routes.SearchPage.search()) {
<input type="text" name="term">
}
will work for a search term, but only as long as "term" is a public variable of the class in which we are going to store the post data.
Edit:
Currently using a method that inserts the empty form. The problem is that the Html class is not found. I have no idea where it is located.
public static Html renderMainLayout(String title, java.util.ArrayList<String> content) {
play.data.Form<Search> userForm = play.data.Form.form(Search.class);
return layout.render(title, content, userForm);
}

Knockout 2: How to delay observable object.

Hi i have a problem in knockout 2: I want to do late binding because i am adding data-bind via jQuery
$("#button1").on ("click", function() {
lateBinding = $("#lateBindingElem);
if (lateBinding.length) {
lateBinding.attr("data-bind", "text: obs");
}
}
});
late binding is an html generated on the fly.
I have a view model created already call MyViewModel.
I want to add another attribute or another observable (could be computed or uncomputed) on the fly to existing view model? How would i do this?
Hopefully you have already found an answer elsewhere (7 months ago :D) but since I stumbled upon this question in hopes to find a solution to a similar problem, I might as well and try to give a sort-of-an-answer for anyone else looking into it. This won't let you manipulate the binding for elements you already have bound to a model but allow you to pause binding at given points and bind newly created elements to your current or a different viewmodel.
Built on Ryan Niemeyers great article about how to stop bindings and accompanying jsfiddle example is a little demo which adds new input elements to dom and binds them to different viewmodels.
Since you can only bind a section of your dom once you need to stop the downward binding at some point using a custom binding..
ko.bindingHandlers.stopBinding = {
init: function() {
return { controlsDescendantBindings: true };
}
};
assign it to a wrapper
<div data-bind="stopBinding: true" id="addNewContentHere"></div>
and insert your new elements
function addInput(){
var data=$('<input type="input" data-bind="value: newInput" />');
ko.applyBindings(MyViewModel, data[0]);
$('#addNewContentHere').append(data);
};
hope it is of some use :)

How to validate and post data from dynamic form in ASP.NET MVC 2

I have an existing ASP.NET MVC 2 application that I've been asked to extend. I am adding a new feature to the site where I generate an employee assessment form based on a dynamic list of questions retrieved from our HR system. I have everything working with the exception of validation and posting the responses back to the site. Here's some details:
I retrieve a list of "Questions" from our back-end system via a web service call.
Each "Question" contains the text to display as well as the following settings:
The question Type (corresponds to textbox, textarea, radio button list or checkbox list)
If comments are allowed
If an answer is required
When applicable, the list of possible responses
To generate the form, I use a for-each loop over the list of Questions. I use the value of the QuestionType property to determine which partial view to render (one for each of the types). For example, if QuestionType == SingleChoice, that partial renders the choices as a radio button list. If comments are allowed for the question, I also render an additional textarea field to hold the user's comments.
As I said, rendering the form is working fine but now I need to:
A. Enforce when an answer is required. I'm using DataAnnotations for validation everywhere else in the solution but since I'm not working against a static model, I don't see how I can do that.
B. Post the results back to the site. For each question, there can be text entered into a textbox or textarea, a selected value for a radio button list or multiple selected values for a checkbox list. Plus, each question could also have additional text sent back in the form of a comment.
All of the examples that I've seen working with dynamic "lists" are only concerned with posting a single value for each field and it is always the same type (e.g. a list of textboxes). With the variations I have to support, plus the need to send back the entered/selected value(s) and a comment for each question, I'm stumped.
Any guidance is appreciated.
I've just finished completing exactly the same task.
I chose to write a custom model binder for my dynamic form object. The model binder pulled out a bunch of prefixed form keys for hidden fields which contained some delimited meta data about the question (i.e IsRequired, QuestionType, QuestionId etc etc)
I'm using MVC3 but I think this should all work in MVC2.
I created a ModelBinder like:
public class DynamicFormModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// Create the object to be bound to (I had a kind of form object
// with a simple list of answer objects
DynamicForm form = new DynamicForm(new List<Answer>());
HttpRequestBase request = controllerContext.HttpContext.Request;
var keys = request.Form.AllKeys.Where(k => k.StartsWith("MyFormsKeyPrefix_Meta_"));
foreach (var key in keys)
{
// Loop over each question's meta data. Metadata will always be present
// even if the user hasn't selected an answer as it's a hidden field
// TODO: Split the meta data and pull out IsRequired, QuestionType etc
// TODO: Get all the posted form values for the question (these values
// will come from textboxes, dropdowns, checkboxes etc)
// Use a prefix like: MyFormsKeyPrefix_Answer_{QuestionId}
// textboxes & dropdowns will only ever have one value
// but checkboxes could have multiple
// TODO: If it's a mandatory question then ensure there is at least
// one posted value that is not an empty string
// If there is a validation error then add it to the model state
bindingContext.ModelState.AddModelError(key, "Field is required");
foreach(var answerHtmlName in answerHtmlNames)
{
// TODO: Loop over each posted answer and create some kind of nice
// Answer object which holds the QuestionId, AnswerId, AnswerOptionId
// and Value etc.
// Add the answer to the forms answers list
form.Answers.Add(answer);
}
}
return form;
}
}
I register the ModelBinder in Global.asax using the following:
ModelBinders.Binders.Add(typeof(DynamicForm), new DynamicFormModelBinder());
So, the action method that recieves the form post looks something like:
public ActionResult ProcessForm(DynamicForm form) {
if(ModelState.IsValid)
{
DynamicFormService.Process(form);
return RedirectToAction("TheHttpGetAction");
}
return TheHttpGetAction();
}