nemo_87 nemo_87 - 1 month ago 9
AngularJS Question

Hide label if 3 drop downs are not selected in AngularJs

I am trying to do what is seemed like a simple thing to me. But since I am very new to angular and mostly with back-end technologies experience I cannot help myself but to ask, is if condition has different behavior in Angular than in other programming languages?

What I am trying to do is:


  • I have 3 drop downs, and hidden label. If all 3 of drop downs has selected value I simply want to show the label.



What I have coded until now is:

Code for controls:

On select elements I have put ng-change so every time when user do some change, function is triggered.

<div class="col-md-2" ng-class="{ 'has-error has-feedback': addNewTestSession.sessionStartTime.$touched && addNewTestSession.sessionStartTime.$invalid }">
<label for="sessionStartTime">Session Start Time<span class="mandatory">*</span></label>
<select id="sessionStartTime" name="sessionStartTime" class="form-control"
ng-model="newTestSessionCtrl.formData.sessionTime"
ng-options="time for time in newTestSessionCtrl.viewData.sessionStarTimeIntervals"
ng-required="true"
ng-change="newTestSessionCtrl.checkIfAllValuesAreSelected()">
<option value="" disabled selected>Select</option>
</select>
<span ng-show="addNewTestSession.sessionStartTime.$touched && addNewTestSession.sessionStartTime.$invalid"
class="fa fa-warning form-control-feedback"
uib-popover="This field is required."
popover-trigger="'mouseenter'"
popover-placement="auto right"
popover-class="additional-info"></span>
</div>
<div class="col-md-1">
<label for="timeZone">Time zone</label>
<select id="timeZone" name="timeZone" class="form-control"
ng-init="newTestSessionCtrl.formData.timeZone = newTestSessionCtrl.viewData.timeZones[15]"
ng-model="newTestSessionCtrl.formData.timeZone"
ng-options="timeZone.name for timeZone in newTestSessionCtrl.viewData.timeZones track by timeZone.name"
ng-change="newTestSessionCtrl.checkIfAllValuesAreSelected()">
</select>
</div>
<div class="col-md-2" ng-class="{ 'has-error has-feedback': addNewTestSession.sessionCloseTime.$touched && addNewTestSession.sessionCloseTime.$invalid }">
<label for="sessionCloseTime">Session to start within<span class="mandatory">*</span>
<i class="fa fa-question-circle"
uib-popover="Interviewee must start the Personal Test Session within this time-window counted from the session's start date & time."
popover-trigger="'mouseenter'"
popover-placement="auto right"
popover-class="additional-info"></i>
</label>
<select id="sessionCloseTime" name="sessionCloseTime" class="form-control"
ng-model="newTestSessionCtrl.formData.sessionCloseInterval"
ng-options="time.name for time in newTestSessionCtrl.viewData.sessionCloseIntervals"
ng-required="true"
ng-change="newTestSessionCtrl.checkIfAllValuesAreSelected()">
<option value="" disabled selected>Select</option>
</select>
<span ng-show="addNewTestSession.sessionCloseTime.$touched && addNewTestSession.sessionCloseTime.$invalid"
class="fa fa-warning form-control-feedback"
uib-popover="This field is required."
popover-trigger="'mouseenter'"
popover-placement="auto right"
popover-class="additional-info"></span>
</div>


On label I have put ng-show property that will be true or false depending on the result of function:

<div class="col-md-2">
<lable ng-show="newTestSessionCtrl.checkIfAllValuesAreSelected()">Your local time</lable>
<div>{{date | date:'yyyy-MM-dd hh:mm'}}</div>
</div>


Angular functionality looks like this:

Two very simple, straightforward functions: isUndefinedOrNull will check if value of drop down is some object or null or undefined and it will return Boolean value.

checkIfAllValuesAreSelected() will call isUndefinedOrNull function for all 3 of drop downs and only if all of them has values it will return true, otherwise it will be false.

isUndefinedOrNull(val) {
return angular.isUndefined(val) || val === null;
}

checkIfAllValuesAreSelected() {
if (this.isUndefinedOrNull(this.formData.sessionCloseInterval) && this.isUndefinedOrNull(this.formData.timeZone)
&& this.isUndefinedOrNull(this.formData.sessionTime)) {
return false;
}
else{
return true;
}
}


What is the outcome: Label is always visible, and when I am using debug mode in Chrome functions are revisited many times. I have feeling that it comes to if part, checks first value, if it is not null object returns true, than check second it it is null it will return false, but it will check third value anyhow. So I am kind of lost.
Does someone sees what I am doing wrongly and not getting clearly?

Answer

First off, you don't need the checkIfAllValuesAreSelected() at all. You can simply change the label to this:

<div class="col-md-2">
    <label ng-show="newTestSessionCtrl.formData.sessionTime && newTestSessionCtrl.formData.timeZone && newTestSessionCtrl.formData.sessionCloseInterval">Your local time</label>
    <div>{{date | date:'yyyy-MM-dd hh:mm'}}</div>
</div>

Then remove the function from your controller and remove the ng-change attributes and you should be all set. Angular will autmatically update the label's visibility once any of the three values change because of the ng-model binding.