Angular JS: ngShow isn't binding my change - javascript

I've got an Angular module here within a larger rails project. I'm new to Angular and wish to avoid jQuery if I can (but do use it throughout the rails project and can use it if necessary). What I'm trying to do is hide a checkbox if the End Time is "", and show a checkbox if there's a value in the End Time. Unfortunately I have been unable to hide it if End Time is "". See:
You can see my HTML code below:
<div class="control-group span8">
<h4 class="pull-left"><strong>Active Hours (UTC):</strong></h4>
</div>
<div class="control-group span1">
<label class="control-label label-unstyled font-size-14" for="inputStartTime">Start Time</label>
<div class="controls">
<select ng-model="geoRegion.start_time" id="inputStartTime" class="input-small" ng-options="thisHour.value as thisHour.name for thisHour in hours" value="{{geoRegion.start_time}}"></select>
</div>
</div>
<div class="control-group span1">
<label class="control-label label-unstyled font-size-14" for="inputEndTime">End Time</label>
<div class="controls">
<select ng-model="geoRegion.end_time" id="inputEndTime" class="input-small" ng-options="thisHour.value as thisHour.name for thisHour in hours" value="{{geoRegion.end_time}}"></select>
</div>
</div>
<div class="control-group span8">
<div ng-show="clearGeoSegment(geoRegion.end_time)"><label class="inline checkbox label-unstyled font-size-14"><input type="checkbox" id="clearGeoSegment" ng-model="geoRegion.clear_segment">Clear Geo Segment at end of active time period.</label></div>
</div>
<div class="control-group span8">
<p id="broadcast-notice" class="pull-left font-size-14"><strong>Note:</strong> If active hours is blank, the Geo Segment is always active.</p>
</div>
My controller code (yes, I used jQuery. But please suggest otherwise!):
$scope.clearGeoSegment = (endTime) ->
if endTime is ''
$('#clearGeoSegment').hide()
else
$('#clearGeoSegment').show()
Any help would be greatly appreciated!

So you don't need to do the hide/show with jquery. You need to just bind to an expression that will be truthy when the checkbox should be visible. In this case it should be as simple as:
<div ng-show="geoRegion.end_time">
And you can delete your clearGeoSegment function entirely.

Related

calculate with select tag

I want that if I choose 75'000 or 100'000 either the result in "one" (see pic 2) is 100 or 1000000. Can you help me do it? I would appreciate your help!
here is my code so far:
<div class="container content-center" id="margin">
<form name="formcalc">
<div class="form-group row">
<label for="staticEmail" class="col-sm-2 col-form-label">select</label>
<select class="col-sm-10 form-control">
<option>Default select</option>
<option>75'000</option>
<option>100'000</option>
</select>
<!-- <div class="col-sm-10">
<input type="tel" class="form-control" name="txtnum1">
</div> -->
</div>
<fieldset disabled>
<div class="form-group row">
<label for="staticEmail" class="col-sm-2 col-form-label">One</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="n1" name="txtres" value="CHF " readonly>
</div>
</div>
<div class="form-group row">
<label for="staticEmail" class="col-sm-2 col-form-label">Two</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="n2" name="txtres2" value="CHF " readonly>
</div>
</div>
</fieldset>
<input type="button" id="btn6" class="btn btn-danger" value="Berechnen" onClick="sumValues();showDiv();">
<button type="button" style="display:none;" class="btn btn-outline-danger" id="toggle" data-toggle="modal" data-target="#exampleModal">
ohne Gewähr
</button>
</form>
<hr class="featurette-divider">
</div>
<select id="selectOne" class="col-sm-10 form-control" onchange="setOne()">
<option>Default select</option>
<option>75'000</option>
<option>100'000</option>
</select>
. . . . .
. . . . .
. . . . .
<script>
function setOne()
{
const selectOne = document.getElementById("selectOne");
if (selectOne.options[selectOne.selectedIndex].text == "75'000")
document.getElementById("n1").value = "100";
else if (selectOne.options[selectOne.selectedIndex].text == "100'000")
document.getElementById("n1").value = "1000000";
}
</script>
The exact requirements are a little unclear, and it sounds like your a relative beginner in front end development. Given that, I will treat this a little bit more as a learning experience than an exact answer to your exact question, so here are some assumptions:
Based on the markup, it looks like this is Bootstrap, so I'm going to assume jQuery is available (if jQuery is not included, it's easy enough to Google search to find out how to do that).
Let's also assume you're just including a <script></script> tag before the closing </body> tag - inside these tags is where your JavaScript code will go.
And finally, as I mentioned your exact requirements were a little unclear, but I know that generally you want a value in a textbox to be set when a value from a select dropdown is chosen. So let's assume that your exact requirement is: you have a dropdown and a textbox. In the dropdown (<select>), you can choose from 2 values: 75,000 and 100,000. If you choose 75,000, the value of the textbox becomes 100, and if you choose 100,000, the value of the textbox becomes 1000000.
Ok so here's the code. It involves what's called an event listener - the browser is listening for a user event like clicking something or (in your case) a select dropdown value being changed. You're going to write code to listen for and respond to that event. In jQuery the syntax is pretty clear and succinct in this way, using the .on() method.
Given this HTML:
<select id="mySelect">
<option>Default select</option>
<option value="75,000">75,000</option>
<option value="100,000">100,000</option>
</select>
<input type="text" id="myTextbox">
Your JavaScript would look like this:
$('#mySelect').on('change', function() {
let textboxValue;
switch(this.value) {
case '75,000':
textboxValue = '100';
break;
case '100,000':
textboxValue = '1000000';
break;
default:
textboxValue = '';
}
$('#myTextbox').val(textboxValue);
});
Here's a JS Fiddle of the working code: https://jsfiddle.net/j06sw8af/1/
This should be enough to get you on track for solving your exact problem.

How to use HTML template tag with jQuery?

Something strange bug is going on in my code. I want to use HTML template tag with jQuery, because all the rest of my code is jQuery, but I only found JavaScript examples with it. I tried to "translate" from JavaScript to jQuery, this is what I came up with.
$.getJSON( "../Controller/ControllerBookstore.php?show_books=true", function( data ) {
$.each( data, function( index, value ) {
// let clone = document.getElementById('table-template').content.cloneNode(true);
// clone.querySelector('#id').innerText = value.id;
// clone.querySelector('#author').innerText = value.author;
// clone.querySelector('#title').innerText = value.title;
// clone.querySelector('#isbn').innerText = value.isbn;
let clone = $("#table-template").clone(true);
$("#id",clone).text(value.id);
$("#author",clone).text(value.author);
$("#title",clone).text(value.title);
$("#isbn",clone).text(value.isbn);
//$(".container").append(clone);
$("#header").append(clone);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div id="myAlert" class="alert alert-success collapse">
<span id="alert-text"></span>
<a id="alert-close" class="close" href="#" aria-label="Close">×</a>
</div>
<div class="row" id="header">
<div class="col"><h5>ID</h5></div>
<div class="col"><h5>Author</h5></div>
<div class="col"><h5>Title</h5></div>
<div class="col"><h5>ISBN</h5></div>
<div class="col"><h5>Action</h5></div>
</div>
<template id="table-template">
<div class="row">
<div class="col" id="id"></div>
<div class="col" id="author"></div>
<div class="col" id="title"></div>
<div class="col" id="isbn"></div>
<div class="col buttons">
<button class='btn btn-info edit'>Edit</button>
<button class='btn btn-danger delete'>Delete</button>
</div>
</div>
</template>
<div class="row justify-content-center" >
<form action="" class="col-4">
<input id = "id-box" type="hidden" name="id">
<div class="form-group row">
<label class="col-4">Author</label>
<input id = "author-box" type="text" class="form-control col-8" name="author" placeholder="Enter the author of the book">
</div>
<div class="form-group row">
<label class="col-4">Title</label>
<input id = "title-box" type="text" class="form-control col-8" name="title" placeholder="Enter the title of the book">
</div>
<div class="form-group row">
<label class="col-4">ISBN</label>
<input id = "isbn-box" type="text" class="form-control col-8" name="isbn" placeholder="Enter the ISBN of the book">
</div>
<div class="form-group row">
<button id = "submit" type="submit" name="save" class="btn btn-primary col-12">Save</button>
</div>
</form>
</div>
</div>
For some reason the JavaScript code I commented out works, but it only appends "clone" to my ".container" correctly, on the next line below the form. However I want to attach it to my ".header", but it attaches next to the header, not below it. The jQuery code doesn't do anything, it doesn't attach my "clone" anywhere.
I hope I was clear. Could you please help me to find the reason of the bugs?
A few changes are needed:
The id value of the template has a hyphen which must be escaped in the selector. Two backslashes are needed in the string literal; the first is needed to actually get a backslash in the string. The remaining one will be interpreted by the selector.
Clone the row element within the template, not the template itself. However, jQuery will not know of a DOM within the template tag, so you could just take the HTML content instead of cloning, and then turn that into a jQuery object again (which produces the DOM for it).
Insert the clone just before the template
Code:
let clone = $($("#table\\-template").html()); // <--------
$("#id",clone).text(value.id);
$("#author",clone).text(value.author);
$("#title",clone).text(value.title);
$("#isbn",clone).text(value.isbn);
$("#table-template").before(clone); // <------
As others have commented, id attributes should have unique values, so your template content cannot have id properties (since it gets cloned). Use class attributes instead.
jQuery bug
Hello my friend. You are cloning the incorrect element, because your create a clone of template with the id #table-template. Please, make this change to your code:
...
let clone = $("#table-template").html();
...
The other thing, the cloned code appears next to #header and not below it because you are using a .row class. I propose to create a div below the #header, with the id="body" and append the new content inside:
...
// $("#header").append(clone);
-> $("#body").append(clone);
...
Thanks for the example.
But I don't change the id of the "collapse" div.
The rest of the objects are cloned normally.
<template id="facilities_template">
<div class="collapse">
<div class="form-check icon-check">
<input class="form-check-input" type="checkbox">
<label class="form-check-label font-14" id="facilities_name" ></label>
<i class="icon-check-1 far fa-square color-gray-dark font-20"></i>
<i class="icon-check-2 fa fa-check-square font-20 color-green-dark"></i>
</div>
<div class="mb-3"></div>
</div>
</template>
JavaScript:
let cloneFacility = $($('#facilities_template').html());
$('#facilities_name', cloneFacility).text(value.name);
$('#facilities_name', cloneFacility).attr('data-facility-id', value.id);
$('#collapse', cloneFacility).attr('id','collapse'+ value.id)
$('#facilities_template').before(cloneFacility);
$('#faсility_filter').append(cloneFacility);

Having trouble targeting a single input among multiple elements with the same class name (jQuery)

I have a page with a list of li elements, each called .section. The page starts with just one section, but the user can add more with a click. Each section has a dropdown called .wip-location and three input fields called .section-number, .section-name, and .section-description. (The -number and -description inputs are irrelevant but I included them here just in case they are causing problems.)
Every time the dropdown is changed, I'd like the selected text to get filled into the .section-name input.
This works the first time (when there is only one .section, .wip-location, and .section-name on the page), but as soon as the user adds more .sections, it appears that Jquery is unable to figure out which element to act upon, and no inputs are filled.
HTML
<li class="section">
<div class="form-group row">
<label class="col-sm-2 text-sm-right">Section Number</label>
<div class="col-sm-7">
<input class="section-number" type="number" step="0.01" min="1" />
</div>
<label class="col-sm-2 text-sm-right">Section Name</label>
<div class="col-sm-7">
<input class="section-name" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 text-sm-right">Section Description</label>
<div class="col-sm-7">
<textarea class="section-description" />
</div>
<label class="col-sm-2 text-sm-right">WIP Location</label>
<div class="col-sm-7">
#Html.DropDownListFor(m => m.WipLocation,
new SelectList(Model.WipLocations, "Key", "Value"),
"-- select --",
new { #class = "wip-location" })
</div>
</div>
</li>
jQuery
// Automatically add Wip Location choice to Section Name input
$('.wip-location').change(function () {
var $location = $('option:selected', $(this)).text();
var $section = $(this).closest('.section');
var $sectionName = $section.find('.section-name');
$sectionName.val($location);
});
As I said, when there is only one .section and .wip-location on the page, it works perfectly. I suspect jQuery gets confused when there are multiple .wip-locations or something, but I'm not sure if that's really the problem or how to fix it.
Since it is dynamically added you could try to call the event like this:
$(document).on('change', '.wip-location', function(){/*...*/})

Razor View - jQuery .val() is updating some components visually -- but not all

I have a search feature built into a page that hits an API to get a list of items if a user chooses to search instead of manually enter (in an attempt to get some clean data). I have the first column of said table set to call a JavaScript function onclick. That function looks similar to this:
function loadDataFromTable(fname, lname, mname, stn, grade, school) {
$('#StudentFirstName').val(fname);
$('#StudentLastName').val(lname);
if (mname !== "undefined") {
$('#StudentMiddleName').val(mname);
}
else {
$('#StudentMiddleName').val('');
}
$('#StudentNumber').val(stn);
$('#Grade').val(grade);
$('#School').val(school);
return false;
}
The associated HTML elements are all ASP.NET Core Razor View input elements. They look like this:
<div class="form-group">
<label class="col-md-3 control-label">Last Name</label>
<div class="col-md-9">
<input type="text" asp-for="StudentLastName" class="form-control" />
<span asp-validation-for="StudentLastName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">STN</label>
<div class="col-md-9">
<input type="text" asp-for="StudentNumber" class="form-control" />
<span asp-validation-for="StudentNumber" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label">Grade</label>
<div class="col-md-9">
<input type="text" asp-for="Grade" class="form-control" />
<span asp-validation-for="Grade" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="School" class="col-md-3 control-label"></label>
<div class="col-md-9">
<select asp-for="School" asp-items="ViewBag.SchoolList" class="form-control"></select>
<span asp-validation-for="School" class="text-danger"></span>
</div>
</div>
Now, if a user clicks on one of the links from the table, all of the values are properly passed into the function, and all of the values for First Name, Last Name, Middle Name, and STN properly update on the view. Grade and School do not update on the View, but their value attribute does update. When I submit the form after the data fills, the correct values are passed to my controller.
What I can't figure out is why the Grade and School values are not populating on the view. The only thing that stands out as different for these two are within the model they are nullable integers, whereas other fields are strings.
I have tried a mixture of .attr('value', grade), .text(grade), and .val(grade), and none of them are working. I can verify that the proper elements are being selected because if I output $('#Grade') I get the input object.

How to validate input field inside ng-repeat

I want to validate an input field where i want to be able to check whether the current input is greater than the previous input.
Here is what i mean
<div class="col-xs-10" ng-repeat="period in trim.rent_period" >
<div class="col-xs-6">
<div class="form-group">
<label class="col-xs-5 control-label" for="rentperiod">Rental Period
<span class="colon--label">:</span>
</label>
<div class="col-xs-6">
<input id="rentperiod" name="rentperiod" type="text" class="form-control" ng-model="rent.period" ng-change="checkRentPeriod($index);" required>
</div>
</div>
</div>
</div>
<div class="col-xs-2">
<i class="pull-left fa fa-plus-circle add-rent--icon" ng-click="addRent(currentIndex);"></i>
</div>
Here the add button adds an input into the list , and i want to make sure that the current input is greater than the previous input.
Try to wrap your code with form tag. And then check for validation of form if everything is okay. You can do this by following this guide here as a way to solve your question
https://docs.angularjs.org/guide/forms
change your ng-model="rent.period" to correct, something starting from "period", like ng-model="period.rent"
no need for extra method ng-change="checkRentPeriod($index);"
add that simple block after input:
<span ng-if="$index > 0 && period.rent && period.rent > trim.rent_period[$index - 1].rent">
Rent is greater than {{trim.rent_period[$index - 1]}}
</span>

Categories