How to call Javascript function from thymeleaf th:text attribute? - thymeleaf

I want to make my language selector display flags instead of language names
I have my flags.js file, which contains the following info
let flags = [
{
"code": "AD",
"emoji": "🇦🇩",
"unicode": "U+1F1E6 U+1F1E9",
"name": "Andorra",
"title": "flag for Andorra"
},
...
];
let getFlagByCountryCode = (countryCode) => {
flags.find((flag) => {
return flag.code === countryCode.toUpperCase();
})
};
And I have my thymeleaf rendered select for languages
<select title="Language" id="locales" style="position: absolute; top: 10px; right: 10px;">
<th:block th:each="locale : ${#resourceService.getLocales()}">
<option th:value="${locale.language}"
th:text="'getFlagByCountryCode(' + ${locale.language} + ')'"
th:selected="${locale.language}==${T(org.springframework.context.i18n.LocaleContextHolder).getLocale().language}">
</option>
</th:block>
</select>
But instead of calling the JS function, it just displays the value as text

You can use javascript in thymeleaf by using tag in thymeleaf page.Let me show you one example:
This is my HTML page:
<input id="ok" type="submit" onclick="redirection()"/>
You can use javascript as:
<script type='text/javascript'>
"Your java script code"
</script>

Related

Angular Material Dialog with Google Places Autocomplete dropdown positioning

I have a web page that uses the Angular framework and therefore the Materials UI library. I have a dialog with a form that uses the Google Places Autocomplete functionality, but the positioning of it stays constant when scrolling through the dialog. Without the dialog, the autocomplete positioning works as I would like and stays directly beneath the input. No styling on the .pac-container has been done for the positioning. The dialog and non-dialog have the same code and styling. Thank you in advance! (Mind the ugliness, it is all testing right now)
google.maps.places.Autocomplete position offset inside angular material Dialog is the exact issue I am having (I think), but I do not know what is meant by "My solution was to remove the top style and then restore it."
Initial position of autocomplete in the dialog
Autocomplete position when scrolling through the dialog
Initial position of autocomplete outside dialog
Autocomplete position when scrolling outside dialog
Non-Dialog TS:
export class AddressTestComponent implements OnInit, AfterViewInit {
#ViewChild("addressLine1") addressField1: ElementRef;
#ViewChild("addressLine2") addressField2: ElementRef;
#ViewChild(MatAutocompleteTrigger, {static: false}) trigger: MatAutocompleteTrigger;
addressForm: UntypedFormGroup;
googleAutocomplete: google.maps.places.Autocomplete;
constructor(private formBuilder: UntypedFormBuilder) { }
ngOnInit(): void {
this.addressForm = this.formBuilder.group(
{
addressLine1: ['', Validators.required],
addressLine2: [''],
city: ['', Validators.required],
state: ['', Validators.required],
zipCode: ['', Validators.required],
country: ['', Validators.required],
}
);
}
ngAfterViewInit(): void {
this.googleAutocomplete = new google.maps.places.Autocomplete(this.addressField1.nativeElement as HTMLInputElement, {
componentRestrictions: { country: ["us"] },
fields: ["address_components"],
types: ["address"]
});
this.addressField1.nativeElement.focus();
this.googleAutocomplete.addListener("place_changed", () => this.autocomplete(this.googleAutocomplete.getPlace()) );
}
}
Non-Dialog HTML:
<div>
<div class="dialog-header">
<h2>Add a New Address</h2>
<h2 class="header-closer" (click)="onClose()" >X</h2>
</div>
<form [formGroup]="addressForm" (ngSubmit)="onSubmitNewAddress()" class="address-form">
<div class="address-wrapper">
<mat-form-field (keydown.escape)="$event.stopPropagation()"
appearance="fill">
<mat-label>Address Line 1</mat-label>
<input matInput #addressLine1 formControlName="addressLine1" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Address Line 2 (Optional)</mat-label>
<input matInput #addressLine2 formControlName="addressLine2">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>City</mat-label>
<input matInput formControlName="city" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>State</mat-label>
<input matInput formControlName="state" required>
</mat-form-field>
<mat-form-field appearance="fill" style="margin-bottom: 10px;">
<mat-label>Zip Code</mat-label>
<mat-hint align="end">{{ zipcode.value.length }} / 5</mat-hint>
<input matInput #zipcode type="tel" [maxLength]="5" formControlName="zipCode" required>
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Country</mat-label>
<input matInput formControlName="country" required>
</mat-form-field>
</div>
<div class="form-buttons">
<button mat-raised-button (click)="onClose()">Cancel</button>
<button mat-raised-button color="primary" type="submit" [disabled]="this.addressForm.invalid">Use This Address</button>
</div>
</form>
</div>
Non-Dialog SCSS:
.dialog-header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 5px;
}
#map {
height: 100%;
}
.address-form {
padding-bottom: 2000px; // for scrolling test
}
.header-closer {
cursor: pointer;
color: red;
margin-top: 30px;
}
.address-wrapper {
display: flex;
flex-wrap: wrap;
mat-form-field {
margin: 0 15px;
flex: 1;
}
}
.form-buttons {
button {
margin: 0 5px;
}
button:hover {
background-color: #771f1f;
}
}
I have tried the autocomplete without a Material Dialog and it works just as intended and how I would like it to work. I am just trying to replicate that while scrolling through the dialog as well. To fix the issue, I tried to change the position styling of .pac-container but was unsuccessful.
EDIT: I figured out what the other stackoverflow link was talking about. Is there a way the autocomplete styling can be tied to the actual input element rather than the html tag?

Select2 with tags set to true: Is it possible to always keep the placeholder after selecting the options?

I want the placeholder to be shown always whether the option is added, selected, or removed. Currently, the placeholder shows after removing the options or after adding the new options. But when the option is selected from the dropdown the placeholder will disappear. This may be the original functionality of the seelct2 plugin. Is there any way to keep the placeholder always visible?
$("select.add-tags").select2({
tags: true,
dropdownParent: $(".select-tags"),
placeholder: "Start typing the tag name..."
});
if ($("select.add-tags").select2("data").length) {
$("select.add-tags")
.next()
.find(".select2-search.select2-search--inline .select2-search__field")
.attr("placeholder", "Placeholder on default");
$("select.add-tags")
.next()
.find(".select2-search.select2-search--inline .select2-search__field")
.css("width", "200px");
}
$("select.add-tags").on("select2:select", function (evt) {
// console.log($(this).val());
console.log("select2 : select");
var element = evt.params.data.element;
var $element = $(element);
$element.detach();
$(this).append($element);
$(this).trigger("change");
if (
$(".select2-search.select2-search--inline .select2-search__field").is(
":focus"
)
) {
console.log("tag input fpcused");
$(".select2-search.select2-search--inline").removeAttr("style");
$(
".select2-search.select2-search--inline .select2-search__field"
).removeAttr("style");
$(".select2-search.select2-search--inline .select2-search__field").attr(
"placeholder",
"Placeholder on select"
);
$(".select2-search.select2-search--inline .select2-search__field").css(
"width",
"200px"
);
}
});
$("select.add-tags").on("select2:unselect", function () {
console.log($(this).val());
console.log("select2 : unselect");
if ($("select.add-tags").val().length == 0) {
$(".select2-search.select2-search--inline .select2-search__field").attr(
"placeholder",
"Start typing the tag name..."
);
$(".select2-search.select2-search--inline .select2-search__field").css(
"width",
"100%"
);
$(".select2-search.select2-search--.select2-search__field").css(
"width",
"100%"
);
} else {
$(".select2-search.select2-search--inline .select2-search__field").attr(
"placeholder",
"Add another tag"
);
$(".select2-search.select2-search--inline .select2-search__field").css(
"width",
"200px"
);
$(".select2-search.select2-search--inline").removeAttr("style");
}
});
select {
width: 300px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2-bootstrap-css/1.4.6/select2-bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/css/select2.min.css rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/js/select2.min.js"></script>
<div class="container select-tags">
<select class="add-tags error" multiple="multiple">
<option value="Red">Red</option>
<option value="Yellow">Yellow</option>
<option value="Green">Green</option>
<option value="Blue" selected>Blue</option>
<option value="Pink">Pink</option>
<option value="Black">Black</option>
</select>
</div>
Codepen: https://codepen.io/jagruti23/pen/bGggJZR

Equivalent script of Datatable in angular ui grid [duplicate]

I created a Single HTML - Table - With Export Options, Search, Pagination using Static Data using DataTables.
plnkr.co/edit/n3cbx8GrGoJtOpgbxE32?p=preview
is similar kind of example or working html available in angular-ui-grid
Datatable doesn't works well with huge records. Could you please kindly help with an equivalent html file using angular ui grid..thanks in advance for anything
Thanks.
From what it looks like, you are able to export CSV and PDF. I don't see any evidence of the Excel export working. I am not sure offhand on the print function, however, exporting the PDF and printing would be an option. I can look later if it's a deal breaker.
The JS code is pretty straight forward. I've added some options for the PDF configuration as well.
The code for the exporting function comes verbatim from UI-Grid.info: 312 Exporting Data With Custom UI. It could be converted to buttons if you wanted, but this provides the external export functionality. The little menu in the upper right corner also has these export options, so I've left it for your experimentation. Setting $scope.gridOptions.enableGridMenu to false will turn that off.
JS
$scope.gridOptions = {
enableGridMenu: true,
data: 'data',
paginationPageSizes: [10],
paginationPageSize: 10,
exporterLinkLabel: 'get your csv here',
exporterPdfDefaultStyle: {fontSize: 9},
exporterPdfTableStyle: {margin: [10, 10, 10, 10]},
exporterPdfTableHeaderStyle: {fontSize: 10, bold: true, italics: true, color: 'red'},
exporterPdfOrientation: 'portrait',
exporterPdfPageSize: 'LETTER',
exporterPdfMaxGridWidth: 500,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
},
};
// Verbatim: http://ui-grid.info/docs/#/tutorial/312_exporting_data_complex
$scope.export = function(){
if ($scope.export_format == 'csv') {
var myElement = angular.element(document.querySelectorAll(".custom-csv-link-location"));
$scope.gridApi.exporter.csvExport( $scope.export_row_type, $scope.export_column_type, myElement );
} else if ($scope.export_format == 'pdf') {
$scope.gridApi.exporter.pdfExport( $scope.export_row_type, $scope.export_column_type );
}
};
HTML
<!-- Verbatim: http://ui-grid.info/docs/#/tutorial/312_exporting_data_complex -->
<label>Which columns should we export?</label>
<select ng-model="export_column_type"</select>
<option value='all'>All</option>
<option value='visible'>Visible</option>
</select>
<label>Which rows should we export?</label>
<select ng-model="export_row_type"</select>
<option value='all'>All</option>
<option value='visible'>Visible</option>
<option value='selected'>Selected</option>
</select>
<label>What format would you like?</label>
<select ng-model="export_format"</select>
<option value='csv'>CSV</option>
<option value='pdf'>PDF</option>
</select>
<button ng-click="export()">Export</button>
<div class="custom-csv-link-location">
<label>Your CSV will show below:</label>
<span class="ui-grid-exporter-csv-link">&nbsp</span>
</div>
<div ui-grid="gridOptions" class="grid" style="width:100%"
ui-grid-selection ui-grid-exporter ui-grid-pagination></div>
</div>
Example Plunk

give default value to md-autocomplete

How to pass default value in md-autocomplete?
Image 1 : HTML code
Image 2 : JS code
Image 3 : Output
As you can see, I am not getting any default country as output. Is there any way to do that?
Assign yr SearchText the default value & selectedItem the object.
$scope.local ={
...
searchText : 'Default Value',
selectedItem : 'Default object'
...
}
I write small codepen with autocomplete and default value.
What you must do:
Init main model.
Define model field, used in autocomplete md-selected-item property.
Define callback for loading autocomplete items.
Before save main model extract id (or other field) from associated field.
Main error in your code here:
$scope.local = {
...
selectedItem: 1, // Must be object, but not integer
...
}
(function(A) {
"use strict";
var app = A.module('app', ['ngMaterial']);
function main(
$q,
$scope,
$timeout
) {
$timeout(function() {
$scope.user = {
firstname: "Maxim",
lastname: "Dunaevsky",
group: {
id: 1,
title: "Administrator"
}
};
}, 500);
$scope.loadGroups = function(filterText) {
var d = $q.defer(),
allItems = [{
id: 1,
title: 'Administrator'
}, {
id: 2,
title: 'Manager'
}, {
id: 3,
title: 'Moderator'
}, {
id: 4,
title: 'VIP-User'
}, {
id: 5,
title: 'Standard user'
}];
$timeout(function() {
var items = [];
A.forEach(allItems, function(item) {
if (item.title.indexOf(filterText) > -1) {
items.push(item);
}
});
d.resolve(items);
}, 1000);
return d.promise;
};
}
main.$inject = [
'$q',
'$scope',
'$timeout'
];
app.controller('Main', main);
}(this.angular));
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.0/angular-material.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.0/angular-material.min.js"></script>
</head>
<body ng-app="app" flex layout="column" layout-margin ng-controller="Main">
<md-content layout="column" class="md-whiteframe-z1" layout-margin>
<md-toolbar>
<div class="md-toolbar-tools">
<h3>Form</h3>
</div>
</md-toolbar>
<md-content class="md-whiteframe-z1">
<div class="md-padding">
<md-input-container>
<label for="firstname">First name</label>
<input type="text" name="firstname" ng-model="user.firstname" />
</md-input-container>
<md-input-container>
<label for="lastname">Last name</label>
<input type="text" name="lastname" ng-model="user.lastname" />
</md-input-container>
<md-autocomplete md-selected-item="user.group" md-items="item in loadGroups(filterText)" md-item-text="item.title" md-search-text="filterText">
<md-item-template>{{ item.title }}</md-item-template>
<md-not-found>No items.</md-not-found>
</md-autocomplete>
</div>
</md-content>
</md-content>
<md-content class="md-whiteframe-z1" layout-margin>
<md-toolbar>
<div class="md-toolbar-tools">
<h3>Model as JSON</h3>
</div>
</md-toolbar>
<md-content class="md-padding">
<p>
{{ user | json }}
</p>
</md-content>
</md-content>
</body>
I know this is an old question, but some people may benefit from my solution. I struggled with the problem of the model for the auto-complete being asynchronous and having my autocompletes as part of an ng-repeat. Many of the solutions to this problem found on the web have only a single auto complete and static data.
My solution was to add another directive to the autocomplete with a watch on the variable that I want to set as default for the auto complete.
in my template:
<md-autocomplete initscope='{{quote["Scope"+i]}}' ng-repeat='i in [1,2,3,4,5,6,7,8]'
class='m-1'
md-selected-item="ScopeSelected"
md-clear-button="true"
md-dropdown-position="top"
md-search-text="pScopeSearch"
md-selected-item-change='selectPScope(item.label,i)'
md-items="item in scopePSearch(pScopeSearch,i)"
md-item-text="item.label"
placeholder="Plowing Scope {{i}}"
md-min-length="3"
md-menu-class="autocomplete-custom-template"
>
then in my module:
Details.directive('initscope', function () {
return function (scope, element, attrs) {
scope.$watch(function (){
return attrs.initscope;
}, function (value, oldValue) {
//console.log(attrs.initscope)
if(oldValue=="" && value!="" && !scope.initialized){
//console.log(attrs.initscope);
var item = {id:0, order:0,label:attrs.initscope?attrs.initscope:"" }
scope.ScopeSelected = item;
scope.initialized = true;
}
});
};
});
this checks for changes to the quote["Scope"+i] (because initially it would be null) and creates an initial selected item and sets the autocompletes' selected item to that object. Then it sets an initialized value to true so that this never happens again.
I used timeout to do this.
$timeout(function() {
$scope.local = {selectedItem : 1}
}, 2000);

knockout.js, jquery-ui, button click and param

I'm using jQuery UI to create a "button" to a given html element. I'm using Knockout.js to generate the html element (foreach).
However, I can't find the way how to pass a parameter to the click event for knockout.js generated items. In the following example, the somewhat static sampleButton works, but not the itemButton items.
http://jsfiddle.net/patware/QVeVH/
function ViewModel() {
var self = this;
self.ping = 'pong';
self.items = ko.observableArray([
{ display: 'Cars', id: 1 },
{ display: 'Fruits', id: 2 },
{ display: 'Humans', id: 3 },
{ display: 'Software', id: 4 },
{ display: 'Movies', id: 5 },
]);
}
ko.applyBindings(new ViewModel());
$("#sampleButton").button().data('someData',101);
$("#sampleButton").click(function(e){
alert('clicked sample: [' + $(this).data('someData') + ']');
});
$(".itemButton").button().data('someData',$(this).id);
$(".itemButton").click(function(){
alert('clicked item: [' + $(this).attr('foo') + ']');
});
ping-<span data-bind="text: ping"></span>
<div id="sample">
<div id="sampleButton">
<h3>Sample Button</h3>
Click here too
</div>
</div>
<div data-bind="foreach: items">
<div class="itemButton" data-bind="foo: id">
<h3 data-bind="text:display"></h3>
</div>
</div>​
Consider using ko.dataFor instead of applying data with jquery.
Working sample based on your example http://jsfiddle.net/QVeVH/6/
You can set everything up using a custom binding.
http://jsfiddle.net/jearles/QVeVH/7/

Resources