Update dropdown selection with JQuery in Java Play Framework - javascript

I want to dynamically add field inputs to a form as the user completes it. However, if the user changes a value for a previous field that others depended on, then I want to hide those later fields again and reset their values back to the default. I can show and hide the input fields without a problem. However, no matter what I do, I cannot change the value of the selection dropdown menu.
Here is my script:
$(function() {
$('#type_selection').change(function() {
var case_type = $('#type_selection :selected').val();
if(case_type !== "") { //the default value is an empty string
$('.subtype-panel').slideDown('slow');
}
else {
$('.subtype-panel').slideUp('slow');
$('#subytype_selection').val("").change();
}
});
});
Play template:
#(caseForm: play.data.Form[Case])
#import views.html.common._
#import models._
#implicitFieldConstructor = #{
b3.vertical.fieldConstructor
}
#main("New Case Info") {
<div class="page-header">
<h3>New Case Information<span class="pull-right label label-primary">Open</span></h3>
</div>
<fieldset>
#b3.form(action = routes.CaseController.save()) {
<div class="panel panel-primary">
<div class="panel-heading">Case Type</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
#b3.select(caseForm("caseType"),
options = options(Case.typeOptions),
'_id -> "type_selection",
'_label -> "Case Type",
'_default -> "-- Select a Type --")
</div>
<div class="col-md-3">
#datePicker(caseForm("date"), '_label -> "Date", 'placeholder -> "mm/dd/yyyy")
</div>
</div>
</div>
</div>
<div class="panel panel-primary subtype-panel">
<div class="panel-heading">Case Subtype</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
#b3.select(caseForm("caseSubType"),
options = options(Case.subTypeOptions),
'_id -> "subtype_selection",
'_label -> "Subtype",
'_default -> "-- Select a Subtype --")
</div>
</div>
</div>
</div>
}
</fieldset>
}
The b3 syntax may look a bit odd to you. It comes from a play bootstrap library: http://adrianhurt.github.io/play-bootstrap/
For b3 select fields, the default option is automatically assigned a value of an empty string. This is what I want to change my selection choice back to using JQuery.

The solution is as adis said in his comment. Using _id -> foo changes the id of the entire form-group (the label and the dropdown), but it does not change the id of the selection box specifically. You have to use id -> foo to do that.

Related

Reuse html template in Angular project

I have this html template file, range-details-dialog.tpl.html
<div class="modal-header clearfix text-left">
<h5>Update Range</h5>
</div>
<div class="modal-body">
<form name="form" role="form" class="ng-pristine ng-valid" novalidate ng-submit="updateRange()">
<div class="form-group-attached">
<div class="row">
<div class="col-sm-12">
<div class="form-group form-group-default input-group p-l-10 p-r-10" ng-class="{ 'has-error' : form.$invalid }">
<p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>
</div>
</div>
</div>
</div>
</form>
<div class="row">
<div class="col-sm-8"></div>
<div class="col-sm-4 m-t-10 sm-m-t-10">
<button type="button" class="btn btn-primary btn-block m-t-5"
ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>
</div>
</div>
</div>
Then I want to have another file forced-range-details-dialog.tpl.html
These two files could be one file instead with dynamically populated placeholders.
These are the places were substitution would be needed:
<h5>Update Range</h5> would become <h5>Update Forced Range</h5>
<p ng-show="form.rangeDaily.$error.min" class="help-block">Daily range more than £5</p>
would become:
<p ng-show="form.forcedRangeDaily.$error.min" class="help-block">Forced Daily range more than £5</p>
ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateRange()">Update</button>
, ng-disabled="form.$invalid || promise" promise-btn="promise" ng-click="updateForcedRange()">Update</button>
Is there a way to avoid having two separate template files for the above? Could you please provide some examples, links, or pointers as to how that can be achieved?
Also, I see in the answers that a solution would be to add a boolean parameter inside the component and then call it twice. I am not sure how to call the component though. I have pasted my component below:
angular.module('app.investment.rangeDetails')
.component('pxForcedLimitAmount', {
templateUrl: '/assets/js/apps/range/range-details-dialog.tpl.html',
bindings: {
amount: '<',
isRequest: '<?',
requestedAt: '<?',
#Input() isForced: boolean //<<----I added this based on answers below
},
controller: [function () {
var ctrl = this;
ctrl.$onInit = function () {
ctrl.isRequest = ctrl.isRequest === true || false;
};
}],
});
Seems like only the placeholders need to change, so you can use a variable to decide what placeholder to display on the template. For example:
isForced: boolean;
ngOnInit() {
this.isForced = true; // decide how you want to toggle this
}
on the template:
<h5 *ngIf="!isForced">Update Range</h5>
<h5 *ngIf="isForced">Update Forced Range</h5>
and
<p *ngIf="!isForced" ng-show="form.rangeDaily.$error.min" class="help-block">
Daily range more than £5</p>
<p *ngIf="isForced" ng-show="form.forcedRangeDaily.$error.min" class="help-block">
Forced Daily range more than £5</p>
you can do the same for other tags as well.
From the comments, one way to "determine" the value for isForced is to introduce an input property to the component i.e.
#Input() isForced: boolean;
and invoke the component from elsewhere like:
<app-user [isForced]="true"></app-user>
You can use inputs.Write a component which takes input, and render it in html. then call this component in desired places with its selector
For events use output
See the doc https://angular.io/guide/inputs-outputs

Angular #Input property - missing first value from array

I have a problem with sending values from one component to other. I've got 2 components: report-form and comment-form. Report form have an array of comments. It also show list of comment and button for each of them. After clicking a button It should load modal form with #Input property commentIndex. Problem is that report-form component don't send only(!) first value of array to comment-form. I don't have idea why :/.
Here's some code:
Part of report-form.html:
<div class="form-group row">
<div class="col-md-12 alert alert-dark">Komentarze:</div>
<div class="col-md-12" *ngFor="let comment of comments">{{ comment.content }}
<app-comment-form [commentIndex]="comments.indexOf(comment)"></app-comment-form>
</div>
<br>
<app-comment-form></app-comment-form>
</div>
If I log it on console in comment-form I've got 1,2 in 3 elements array but where's 0?!
You can use index provided by the *ngFor directly.
<div class="form-group row">
<div class="col-md-12 alert alert-dark">Komentarze:</div>
<div class="col-md-12" *ngFor="let comment of comments; let i = index">{{ comment.content }}
<app-comment-form [commentIndex]="i"></app-comment-form>
</div>
<br>
<app-comment-form></app-comment-form>
</div>
This index will start from 0.

Semantic ui dropdown, prevent auto select with input element

I added an option to the dropdown that allows user to add item if it doesn't exist.
For that matter, I added an input field to the dropdown but when the user enters something, the dropdown tries to match the entered text with items that are already in the list.
I find it quite annoying in that specific case. I have noticed in the docs that input elements are bound to the search function. Nevertheless, I couldn't find how to disable this behaviour.
Here's the HTML:
<div class="ui fluid selection dropdown playlist">
<input name="playlist" type="hidden">
<i class="dropdown icon"></i>
<div class="default text">playlist</div>
<div class="menu">
<div class="item create" data-value="0">
<span class="create-placeholder">+ new playlist</span>
<div class="ui action input add-playlist">
<input placeholder="new playlist">
<button class="ui button">Add</button>
</div>
</div>
<div class="item" data-value="1">foo</div>
<div class="item" data-value="2">bar</div>
<div class="item" data-value="3">baz</div>
</div>
</div>
The .add-playlist div and its content are not shown but I'm willing to spare you with the CSS here.
And the js:
$dropdown = $('.ui.dropdown');
$dropdown.dropdown({
action: (text, val) => {
if (val == 0) { // eslint-disable-line
$('.create-placeholder').hide(100);
$('.add-playlist').css('display', 'inline-flex');
$('.add-playlist input, .add-playlist button').show(200);
}
else $dropdown.dropdown('set selected', val).dropdown('hide');
},
onHide: () => {
// do that after dropdown has been hidden
setTimeout(() => {
$('.add-playlist, .add-playlist input, .add-playlist button').hide();
$('.create-placeholder').show();
}, 400);
}
});
I've set up a fiddle to have a clear exemple. Just type "foo" and you'll see what I mean in case it's not crystal clear.
To allow user to add new items just add allowAdditions: True To dropdown options, for more informtions see semantic-ui dropdown settings
Example:
$('dropdownSelector').dropdown({
allowAdditions: True
}).dropdown();

I have a 100 button, click each button to display its corresponding bomb box, With javascript and angular

a button corresponding to a prompt box,each box is different shells;Although implements the desired function, but my code is too complicated, and that there is no simple way. how can I do? This is my code
<--html button-->
button1
button2
...
button100
<--html pop box-->
<div class="note1" style="display:none;">
<img class="title-css" src="note1.png">
<p class="one">note1</p>
</div>
...
<div class="note100" style="display:none;">
<img class="title-css" src="note100.png">
<p class="one">note100</p>
</div>
<--angular js-->
$scope.showRulePop = function(index) {
for(var i=1;i<=8;i++) {
$('.note'+i).hide();
}
$('.note'+index).show();
};
Well first of all, don't use jQuery, unless your in the directive level of angular jQuery have nothing to do there.
First let's get rid of the links part using a simple ng-repeat :
<--html button-->
<div ng-repeat="button in buttons">
{{button.label[i]}}
</div>
// JS in the controller
$scope.buttons = [{
label:'button1'
},{label:'button2'}];
As you can see i declare in the javascript all your buttons and i just loop over it.
Now the "bombox" or whatever it is let's make it a simple template :
<div class="{{currentnote.class}}" ng-if="currentNote">
<img class="title-css" src="{{currentNote.img}}">
<p class="one">{{currentNote.content}}</p>
</div>
// and use ng-repeat for the eight first when there is no button selected
<!-- show 1 to 8 if note current note selected -->
<div ng-repeat="button in buttons1To8" ng-if="!currentNote">
<div class="{{button.note.class}}">
<img class="title-css" src="{{button.note.img}}">
<p class="one">{{button.note.content}}</p>
</div>
</div>
// JS
$scope.buttons = [{
label:'button1'
note:{class:'note1', img:'note1.png', content:'note1'//assuming no HTML or you' ll need something more
}},{label:'button2', note:{...}}, ...];
$scope.showRulePop = function(index){
$scope.currentNote = $scope.buttons[index].note;
}
$scope.buttons1To8 = $scope.buttons.slice(0, 8);//0 to 7 in fact
That's all, no need of jQuery.

MVC5 Radio Button Instant Hide/Show

I used to use this in Web Form development through the id and name of the input radio button, but can't seem to get it in MVC5, could someone point out what I'm doing wrong?
On a radio button (part of the model) selection, depending which button, I want another text box to appear (within a div).
View:
<div class="ui-grid-solo">
<div class="ui-grid-solo">
<div class="ui-block-a">
<p>AS Number Type</p>
<span>
#Html.RadioButtonFor(model => model.NumberType, "Odd", true)Odd
#Html.RadioButtonFor(model => model.NumberType, "Even", false)Even
</span>
</div>
</div>
#if (Model.NumberType == true)
{
<div id="OddOrEven">
<div class="ui-grid-solo">
<div class="ui-block-a">
<span>
#Html.EditorFor(m => m.Reason)
</span>
</div>
</div>
</div>
}
JavaScript:
#section Scripts
{
<script type="text/javascript" src="~/Scripts/maintainscroll.jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("input[Value='Odd']").click(function () {
var test = $(this).val();
$("#OddOrEven").show();
});
});
</script>
}
I would do it like this:
#Html.RadioButtonFor(model => model.NumberType, "Odd", true)Odd
#Html.RadioButtonFor(model => model.NumberType, "Even", false)Even
<div id="OddOrEven">
<div class="ui-grid-solo">
<div class="ui-block-a">
<span>
#Html.EditorFor(m => m.Reason)
</span>
</div>
</div>
</div>
<script>
$("#OddOrEven").hide();
$("input[name='NumberType']").on("change", function () {
if ($(this).val() == "Odd") {
$("#OddOrEven").show();
}
}):
</script>
Basically, grab the change event of your radio button group by the input's name, rather than the value. The issue with using the value is that if you have multiple radio button groups on the same view, and they each have the same value pairs (ie: true/false), then your view would not know which radio group to select. Using name is the proper way to go.
Remove the #if surrounding the div, set the div css class to hidden on page load, then your button will work, however clicking off of it will still leave it there, add to the javascript to hide the textbox again.
So remove that #if change your div to <div id="OddOrEven" style="display:none"> and the below within your script:
$(document).ready(function () {
$("input[Value='Odd']").click(function () {
$("#OddOrEven").show();
});
$("input[Value='Even']").click(function () {
$("#OddOrEven").hide();
});
});

Categories

Resources