I have a view in which I need to insert form fields, into view.
Now these form fields I need to render come f from API request, which basically tells name of field and input type.
So not only I need to insert the template but also fill up input properties basically name attribute.
I am thinking of loading into data into partials, but I am not sure how to load partials dynamically unlike use ng-include
Any help?
Use directives.
You can attach your html template (I'm assuming this is what you mean by partials) to a directive as follows:
.directive('myFormField1', function() {
return {
template: '<label>{{ my_label }}<input></input></label>'
};
});
Then, you can issue your request and bind the data to your scope:
$http.get('/myUrl').
then(function(response) {
$scope.reqData = response.data
}
Finally, you use the request data to dynamically generate your form in the main template. Substitute your own variables and conditions as appropriate.
<form>
<div myFormField1 ng-if="reqData.shouldShowField1 == true"></div>
<div myFormField2 ng-repeat="item in reqData.repeatedData"></div>
</form>
This should point you in the right direction, though without knowing specifics I obviously can't give you a full answer.
Related
I'm making a Spring MVC app using Thymeleaf.
The app contains a Combo Box/Dropdown Menu inside a form. I want every selected value in the Combo Box to be linked to the update of specific fields. I.e.
value 1 -> form updates field 1
value 2 -> form updates field 2
...
I tried by changing the value of th:field using JavaScript, but looks like Thymeleaf tags are "pre-processed" and once the HTML is rendered and the form is associated with a specific field, it stays like that.
What would be the best way to face this problem?
Would it be necessary to trigger the refreshment of the page every time that the value of the Combo changes so that the field that the form updates can vary or there's a better way?
Thanks in advance.
Like you mention, it's not possible to change "th:field" or any thymeleaf-specific attributes after the page has been rendered.
However, "th:field" is usually just a shortcut for setting the "id", "name", and "value" attributes. (See here: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#inputs) So you could update those manually from your Javascript.
Although in this case I think the simplest solution would be to create a new type of object in your Java code with fields that match the fields of your form, and use that object instead. So, for example:
class MyFormDTO {
private String fieldToUpdate;
private String newValue;
// ... getters and setters ...
}
And in your template:
<select th:field="*{fieldToUpdate}">
<option value="field1">Field1</option>
<option value="field2">Field2</option>
</select>
<input type="text" th:field="*{newValue}" />
And your POST handler method:
#PostMapping("/my-form")
public String submitMyForm(MyFormDTO myFormDTO) {
MyBackendObject myBackendObject = MyBackendService.get(...);
switch (myFormDTO.getFieldToUpdate()) {
case "field1": myBackendObject.setField1(myFormDTO.getNewValue()); break;
case "field2": myBackendObject.setField2(myFormDTO.getNewValue()); break;
}
}
...rather than using the "MyBackendObject" (or whatever) directly as the form object.
I've begun a project in Symfony 3 which needs to allow users to create a post with some data, and a collection of tags (many-to-many). The CSS framework I've been using is MaterializeCSS and there's a handy class called 'chips' which would be nice to allow input for the tags.
I've been using the Form objects as per the Symfony guide with no issues so far, however my issue is that the materialize CSS constructs its 'Chips' field like this:
<div class="chips"></div>
...
$('.chips').material_chip();
I can't for the life of me see how to do this inside of a Symfony form, or how to retrieve the data after submission if done with custom form rendering. I could just not use it, but the UX would suffer. I've read a bit about the CollectionType class inside of Symfony but I'm still not sure that this would be appropriate to use with chips.
I'm sure somebody's completed a project like this before, would be great to have some input. All help appreciated.
Did you try something like this ?
{{ form(form.name, { 'attr': {'class': 'chips'} }) }}
I recommend you to read this post
As we discussed above , the idea is to have some glue js code to manipulate a hidden field which contains tags as comma separated values and bind the chip widget with that hidden field as data source and target e.g
Desired html
Input field(might be hidden):
<input name="chips" value="Apple,Hello,World">
The Chip:
<div class="chips"/>
Glue js
<script>
function updateChipInput(chip){
var newval= $(chip).material_chip('data')
.reduce(function(result,val){ result.push(val.tag); return result;},[]).join(",")
$('input[name="chips"]').val(newval);
}
$(document).ready(function(){
var data= $('input[name="chips"]').val().split(',')
.map(function(tag){
return {tag:tag}
})
$('.chips').material_chip({
data: data
});
$('.chips').on('chip.add', function(e, chip){
updateChipInput(this);
})
.on('chip.delete', function(e, chip){
updateChipInput(this);
});
});
</script>
working demo
The input is text field to show the effects in example you can set its type to hidden ,thanks
Scenario:
I have a cascade scenario, where values in second dropdown depends upon first. I have three templates "layout", "input" and "inner".
Attempt:
I'm making ajax call on change of first dropdown in "input" template and stuck with handling the response returned. Currently I found a way to fix it by replacing html of second dropdown. But, I think this is not the better way to handle. I want something in line of rendering templates where I do not need to amend html.
please help in acheiving the task in better way or point to some wiki. Only Standard Library
Thanks,
Layout.html:
http://play.golang.org/p/LikKy6rf3-
Input.html:
http://play.golang.org/p/wM7EpPdXuM
Inner.html:
http://play.golang.org/p/xFpInKZfFT
Main.go:
http://play.golang.org/p/cxtJU-Lhi1
On the higher level you have 2 options:
Either send all the values for the dropdown lists (e.g. as a tree) and change the values on the 2nd and 3rd level when the dropdown of a higher level changes (suitable for small lists, unsuitable for large dataset)
Or the one you chose: when selection changes, you make an AJAX call (triggered from onchange) and you populate the list from the results.
Elaborating #2: populating list from the AJAX call result
You also have 2 options to do this:
Either the AJAX call returns HTML call which you can simply use to replace the inner HTML of the HTML <select> tag.
Or the AJAX call may only return the data (e.g. encoded using JSON), and a Javascript code can build the content of the list.
AJAX returning HTML
The AJAX call may return the complete HTML code needed to be replaced as the inner HTML of the <select>. To achieve this at server side, you can create/separate the HTML template responsible only to generate the HTML code of this, for example:
{{define "innerList"}}
{{range .}}
<option value="{{.Key}}">{{.Text}}</option>
{{end}}
{{end}}
You can execute only this template like this:
// tmpl is the collection of your templates
values := ... // Load/construct the values
tmpl.ExecuteTemplate(w, "innerList", values)
Here values is a slice of the following structure:
type Pair struct {
Key string
Text string
}
Building <select> content with Javascript
The AJAX call may return a JSON datastructure, an array/list of value;text pairs from which you add the <option> child tags yourself.
To add an <option> to a <select> tag:
var x = document.getElementById("mySelect");
var option = document.createElement("option");
option.value = "1234";
option.text = "Kiwi";
x.add(option);
So basically what you need to do is remove current children of the <select>, iterate over the list received as the response and add a new <option> tag constructed from each.
I have been searching around trying to find a solution to this with no success :(
I have a page that lists products. The page has two layouts (list and grid) with a toggle to switch between the views (basically changing the CSS behind the view) this is all working as expected !
I am using full text search on the page containing of a search box (text input) that filters the products based on the entered search string etc... this is also working as expected.
I have a keyup event listener on the text input so that the data is filtered on each key press using an ajax get response. The data is filtered correctly however the view state / switch is not considered.
E.g. the default view is a list. If I do not change the view and search, everything is updated correctly: the correct results renders as a list. However, if I change to the grid view, and then search, although the results are correct the view is switched back to the original (list) view.
The switch toggle also stops working after a search has passed.
I am not sure, but it seems like the $.get methods response reloads the original file not containing any added classes (in relation to the view change) that have been added. It also appears that all JS added on document load is lost.
This is "basically" what I have:
CSS
.hideSection {
display: none;
}
HTML
<form accept-charset="UTF-8" action="/employees" id="employee_search" method="get">
<input autocomplete="off" id="query" name="query" type="text">
</form>
<div class="btn-group">
<button id="listViewButton" type="button" class="btn btn-default btn-sm">LIST</button>
<button id="gridViewButton" type="button" class="btn btn-default btn-sm">GRID</button>
</div>
HTML
<div id="listView" class="list-view">
...
</div>
<div id="gridView" class="grid-view hide-view" >
...
</div>
JS (CoffeScript)
$("#gridViewButton").click ->
$(".gridView").removeClass "hideSection"
$(".listView").addClass "hideSection"
$("#listViewButton").click ->
$(".listView").removeClass "hideSection"
$(".gridView").addClass "hideSection"
$("#employee_search input").keyup ->
$.get $("#employee_search").attr("action"), $("#employee_search").serialize(), null, "script"
false
As said, all searching works as expected, the problem is that the view looses its state (List or Grid) when searching, and additionally all JS appears not to work after the search - im not sure if this is something to do with the response from the $.get method as looking at it in the inspector, it contains the HTML from the original file not the modified file after changing the view etc..
Any help on this in relation to keeping the view state on searching would be greatly appreciated !
Thanks,
Jon.
listView and gridView are id not class and use toggleClass() like,
$("#gridViewButton").click ->
$("#gridView,#listView").toggleClass "hideSection"
$("#listViewButton").click ->
$("#listView,#gridView").toggleClass "hideSection"
The only way I managed to achieve my required behavior was to modify the Ajax GET method, by adding a success handler and modifying DOM data within this handler:
Within my keyup handler, before the GET, I save the current view state (styles added to the view containers) in variables accordingly. Within the GET, in the success handler I modify the result setting the view (styles) to the the new (changed) values (form the set variables) after the DOM was loaded:
$("#employee_search input").keyup (event) ->
alteredListViewHtml = $(".listViewEmployeeContainer").attr("class")
alteredGridViewHtml = $(".gridViewEmployeeContainer").attr("class")
$.get $("#employee_search").attr("action"), $("#employee_search").serialize(), ((result) ->
$(".listViewEmployeeContainer").attr('class', alteredListViewHtml)
$(".gridViewEmployeeContainer").attr('class', alteredGridViewHtml)
viewToggleClickHandlers()
return ), "script"
false
I hope this makes sense and can help someone out !
Cheers,
Jon.
I'm just getting started with emberjs and I have some problems understanding how to dynamically change views within a view.
I want to have a page with a calendar.
This page has some buttons on the top to switch between different calendar views (day, week, month) and some filter options for the appointments within this view.
See this mockup:
Currently I have created a calendar route and a CalendarIndexView and template.
This template will contain the basic filter and view toggle buttons.
Within the index view I can call another view to display the grid.
<div class="calendar-container">
{{view monthView}}
</div>
The collection/context that is attached to these different views should not change because the filter is also applied on this.
The problem I have is that I don't know how to change the monthView to for example dayView after the "day" button is clicked.
Should I handle this in a router, controller or in the main calendar view?
If not view the router, how would make this view switching dynamic?
One of the core strengths of Ember is the router - everything is driven by the URL. I don't think you should part from that.
Use different routes for the different views within a calendar resource (in the router):
this.resource('calendar', { path: '/calendar' }, function() {
this.route('day');
this.route('week');
this.route('month');
});
Set the model on the calendar resource
In the nested routes (day, week (you could make month the default by using the calendar index route for it)), use the same model as in the calendar route, just filter it down to what you want. e.g.:
export default Ember.Route.extend({
model: function() {
return this.modelFor('calendar').filter(function(event) { ... });
}
});
For the people filter create a computed property in the controller that filters the events on the model and use that in the templates instead of the actual model. In that, if a person is selected, you can filter out any events without that person.
selectedPerson: null, // bind that e.g. to a select with all the people or change that with an action
filteredEvents: function() {
if (! this.get('selectedPerson')) {
return this.get('events');
}
return this.get('events').filterBy('attendee', this.get('selectedPerson'));
}.property('events.#each.attendee', 'selectedPerson')
Better than (4.): Do the filtering via query parameters. That way, you could be very flexible and even build powerful text search pretty easily...
Hope that helps and happy to see different approaches...