angular JS view does not update properly - javascript

It's my first day of angular JS so I'm quite a newbie, I'm asking for some explanation about a behaviour that I don't understand. I'm trying to build a form that is composed of "panels". each panel contains a number of form elements (checkbox, radio group, etc.) or a message. At the beginning only the first panel is visible. Each time a user make an "action" (check something, choose something). A panel appears (sometimes more) based on the previous choice and other data.
Each form element has its model inside a controller. Each panel has a directive ngShow and a function in a controller that return whether or not this panel should be displayed. Here is a small extract from my code for two panels :
First Panel (ROOT panel always displayed)
<div class="panel panel-default" data-ng-show="true">
<div class="panel-heading">
<h3 class="panel-title">PLP</h3>
</div>
<div class="panel-body">
<div class="form-group">
<div class="col-xs-offset-0 col-xs-10">
<div class="radio">
<label><input type="radio" name="group" data-ng-model="choixPlp" value="plp1"> PLP 1</label>
</div>
<div class="radio">
<label><input type="radio" name="group" data-ng-model="choixPlp" value="plp2"> PLP 2</label>
</div>
<div class="radio">
<label><input type="radio" name="group" data-ng-model="choixPlp" value="plp3"> PLP3</label>
</div>
</div>
</div>
<p> {{choixPlp}} </p>
</div>
</div>
Second Panel
<div class="panel panel-default"
data-ng-show="fmotifRetourCommentaires()">
<div class="panel-heading">
<h3 class="panel-title">Dépot</h3>
</div>
<div class="panel-body">
<div class="form-group">
<div class="col-xs-offset-0 col-xs-10">
<label> Motif Retour : {{motif}} </label>
<p>Commentaires</p>
<div class="textarea"></div>
<textarea rows="" cols=""></textarea>
<br />
<button type="submit" class="btn btn-default">Déposer</button>
</div>
</div>
</div>
</div>
App.js
var app = angular.module('dynamicForm', []);
app.controller('MainCtrl', function($scope) {
$scope.choixPlp;
$scope.motif;
$scope.fmotifRetourCommentaires = function() {
if ($scope.choixPlp == "plp1") {
$scope.motif = "Degroupage Abusif";
return true;
}
if ($scope.choixPlp == "plp2") {
$scope.motif = "Deconstruction a tort";
return true;
}
return false;
};
});
My problem is that the view doesn't display the value of the variable "motif" in the second panel doesn't change when I change my choice on the first panel. It changes only if I click twice on the new choice. I did add this portion of code and it works but I don't understand why...
setInterval(function() {
$scope.$apply()
}, 500)

The reason it is not working on the first click but on the second click is because the model is not getting set till you the radio button loses focus (I think the sequence of watch and refresh is not proper for some reason)
Since you want to do some action based on the value of choixPlp, you can consider setting a watch on that variable. I have modified your code a little bit and used a variable show_panel_2, and that flag gets set or unset based on the function in watch.
<div class="panel panel-default"
data-ng-show="show_panel_2">
<div class="panel-heading">
<h3 class="panel-title">Dépot</h3>
</div>
<div class="panel-body">
<div class="form-group">
<div class="col-xs-offset-0 col-xs-10">
<label> Motif Retour : {{motif}} </label>
<p>Commentaires</p>
<div class="textarea"></div>
<textarea rows="" cols=""></textarea>
<br />
<button type="submit" class="btn btn-default">Déposer</button>
</div>
</div>
</div>
</div>
<script>
var app = angular.module('dynamicForm', []);
app.controller('MainCtrl', function($scope) {
$scope.choixPlp;
$scope.motif;
$scope.show_panel_2 = false;
$scope.$watch('choixPlp', function() {
if ($scope.choixPlp == "plp1") {
$scope.motif = "Degroupage Abusif";
$scope.show_panel_2 = true;
return;
}
if ($scope.choixPlp == "plp2") {
$scope.motif = "Deconstruction a tort";
$scope.show_panel_2 = true;
return;
}
$scope.show_panel_2 = false;
});
});
</script>

Related

Bootstrap radio buttons wil not fire in google chrome

My radio buttons work normally in Internet Explorer, but in Google Chrome the button don't seem to fire the div.alert_text nor div.question event. So am I missing something in the web kit, or does chrome hit the parent div? I set a debugger and hit it when I run IE, but when I run it in chrome nothing happens, there are bootstrap radio buttons, I put a debugger here:
$(document).ready(function () {
$("div.alert_text").hide();
$("div.question").find(':radio').click(function () {
var isValid = $(this).hasClass('True');
var divAlert = $(this).parents('.question').find('div.alert_text');
debugger
if (!isValid) {
divAlert.show();
$(this).parents('.btn-group').find('.btn').removeClass('btn-success').removeClass('btn-danger');
$(this).parents('.btn').addClass('btn-danger');
}
else {
divAlert.hide();
$(this).parents('.btn-group').find('.btn').removeClass('btn-success').removeClass('btn-danger');
$(this).parents('.btn').addClass('btn-success');
}
// Enable-Disable Next Button
if ($(":radio:checked.True").length == #Model.Count()) {
$("#next").prop("disabled", false).removeClass("k-state-disabled");
}
else {
$("#next").prop("checked", true).addClass("k-state-disabled");
}
})
});
HTML:
#foreach (var item in Model)
{
var id = item.QuestionID.ToString();
var isYesValidAnswer = item.IsYesValidAnswer.Value ? "True" : "False";
var isNoValidAnswer = item.IsNoValidAnswer.Value ? "True" : "False";
<div class="row" style="background-color:darkgray; height:1px"></div>
<div class="question row">
<div class="col-md-10">
<div class="row"><b>#item.Title</b></div>
<div class="row">#item.Question</div>
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-11"><font size="2">#item.YesText</font></div>
</div>
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-11"><font size="2">#item.NoText</font></div>
</div>
<div class="row alert_text">
<div class="col-md-12 k-widget k-notification k-notification-error">Alert! #item.AlertMessage</div>
</div>
</div>
<div class="anwser col-md-2 btn-group" data-toggle="buttons">
<label for="" class="btn btn-default">
<input name="yes_no#(id)" class="#(isYesValidAnswer)" id="yes_no#(id)_True" value="True" type="radio">Yes
</label>
<label for="" class="btn btn-default">
<input name="yes_no#(id)" class="#(isNoValidAnswer)" id="yes_no#(id)_False" value="False" type="radio">No
</label>
</div>
</div>
}

Angular js directive not working in for loop

I am using a diective in ng-repeat which when i click i pass date and time to the function showAppointmentForm but here the problem is when I click on first index of loop i get date and time displayed in modal box but when I click on second ,third and so on its values are coming as function parameters but not displayed.Is this something problem with using directives in for loop.Can anyone please suggest help.Thanks.
Using directive in template,
<div data-ng-repeat="doctor in doctors">
<appointment-timings data-ng-if="appointments" appointments="appointments" physician="doctor.npi" width="2"></appointment-timings>
</div>
My appointmnt directive,
$scope.showAppointmentForm = function(date,time) {
$scope.appointmentData = {};
$scope.appointmentData.physician = $scope.physician;
$scope.appointmentData.date = '';
$scope.appointmentData.time = '';
$scope.appointmentData.date = date.toString();
$scope.appointmentData.time = time;
$scope.submitted = false;
$timeout(function () {
$scope.$apply();
$('#appointments').modal('show');
},500);
}
My Directive html,(A modal box)
<div class="date-time">
<div class="col-md-6 col-xs-6">
<div class="input-group">
<span class="input-group-addon"><b>DATE</b></span>
<input type="text" class="form-control" ng-model="appointmentData.date" disabled>
</div><!-- /input-group -->
</div>
<div class="col-md-6 col-xs-6">
<div class="input-group">
<span class="input-group-addon"><b>TIME</b></span>
<input type="text" class="form-control" ng-model="appointmentData.time" disabled>
</div>
</div>
</div>
<div class="scheduled-hours" id="scheduled-scroll">
<ul>
<li data-ng-click="showAppointmentForm(date, time)" data-ng-repeat="time in times">{{time}}</li>
</ul>
</div>

How to implement multiple filters using checkboxes?

How do I implement multiple filters using checkboxes preferably using jQuery?
I have multiple div elements with their own data attributes which represent the difficulties of levels the user has completed.
I want to create a filter using checkboxes so that when they check a box for a specific difficulty which are completed, that difficulty is filtered out (hidden). If the user wants to filter multiple difficulties, then those difficulties are filtered out as well. If the user unchecks the box, then obviously it reappears.
Here is the div elements containing the data attributes. The data attributes which are set to true are the ones which are completed. E.g. (data-normal=true means normal difficulty is completed)
<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level One" data-completed="2" data-easy="true" data-normal="false" data-hard="true" data-expert="false">
<div class="map-col">
<!--Content Here-->
</div>
</div>
<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level Two" data-completed="4" data-easy="true" data-normal="true" data-hard="true" data-expert="true">
<div class="map-col">
<!--Content Here-->
</div>
</div>
<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="true" data-normal="false" data-hard="false" data-expert="false">
<div class="map-col">
<!--Content Here-->
</div>
</div>
In this example, if I checked expert, then Level Two should become hidden. If I also checked hard, then both Level One and Level Two should be hidden.
Here are my checkboxes
<div class="checkbox">
<label><input type="checkbox" id="hideEasyChkBox">Hide Easy</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideNormalChkBox">Hide Normal</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideHardChkBox">Hide Hard</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideExpertChkBox">Expert</label>
</div>
I did attempt this using a bool for each difficulty however if a box became unchecked despite other boxes being checked, it would unhide all the levels ignoring the fact other boxes are still checked.
If anything is unclear, please ask. Thanks
Edit: Here is the method I used however this does not work as when I uncheck one of the checkboxes, the div's reset and display all the levels ignoring the fact that the other boxes are still checked.
var hideCompleted = false;
var hideEasy = false;
var hideNormal = false;
var hideHard = false;
var hideExpert = false;
function mapCompletionFilter(filterBy){
var $wrapper = $('.map-container');
if(filterBy == "hideCompleted" && !hideCompleted){
//$wrapper.find(".map-col-container[data-completed*=4]").hide();
$wrapper.find(".map-col-container").filter('[data-completed="4"]').hide();
hideCompleted = true;
}
else if(filterBy == "hideCompleted" && hideCompleted){
$wrapper.find(".map-col-container[data-completed*=4]").show();
hideCompleted = false;
}
if(filterBy == "hideEasy" && !hideEasy){
//$wrapper.find(".map-col-container[data-completed*=4]").hide();
$wrapper.find(".map-col-container").filter('[data-easy="true"]').hide();
hideEasy = true;
}
else if(filterBy == "hideEasy" && hideEasy){
$wrapper.find(".map-col-container").filter('[data-easy="true"]').show();
hideEasy = false;
}
if(filterBy == "hideNormal" && !hideNormal){
//$wrapper.find(".map-col-container[data-completed*=4]").hide();
$wrapper.find(".map-col-container").filter('[data-normal*="true"]').hide();
hideNormal = true;
}
else if(filterBy == "hideNormal" && hideNormal){
$wrapper.find(".map-col-container").filter('[data-normal*="true"]').show();
hideNormal = false;
}
if(filterBy == "hideHard" && !hideHard){
//$wrapper.find(".map-col-container[data-completed*=4]").hide();
$wrapper.find(".map-col-container").filter('[data-hard*="true"]').hide();
hideHard = true;
}
else if(filterBy == "hideHard" && hideHard){
$wrapper.find(".map-col-container").filter('[data-hard*="true"]').show();
hideHard = false;
}
if(filterBy == "hideExpert" && !hideExpert){
//$wrapper.find(".map-col-container[data-completed*=4]").hide();
$wrapper.find(".map-col-container").filter('[data-expert*="true"]').hide();
hideExpert = true;
}
else if(filterBy == "hideExpert" && hideExpert){
$wrapper.find(".map-col-container").filter('[data-expert*="true"]').show();
hideExpert = false;
}
}
Buttons
$("#hideAllCompletedChkBox").click(function(){
mapCompletionFilter("hideCompleted");
});
$("#hideEasyChkBox").click(function(){
mapCompletionFilter("hideEasy");
});
$("#hideNormalChkBox").click(function(){
mapCompletionFilter("hideNormal");
});
$("#hideHardChkBox").click(function(){
mapCompletionFilter("hideHard");
});
$("#hideExpertChkBox").click(function(){
mapCompletionFilter("hideExpert");
});
The main issue I am having is when I use multiple checkboxes for hiding each individual difficulty whereby if one of these checkboxes are unticked, all div's become unhidden.
Here, i prepare fiddle t show how it works - https://jsfiddle.net/skyr9999/nynbupwh/
I update you html a bit to make sure and test all works fine.
Here's is html:
<div id="elems">
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level One" data-completed="2" data-easy="true" data-normal="false" data-hard="true" data-expert="false">
<div class="map-col">
Easy, hard
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Two" data-completed="3" data-easy="true" data-normal="true" data-hard="true" data-expert="true">
<div class="map-col">
Easy, Normal, Expert
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="true" data-normal="false" data-hard="false" data-expert="false">
<div class="map-col">
Easy
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="true" data-hard="false" data-expert="false">
<div class="map-col">
Normal
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="true" data-expert="false">
<div class="map-col">
Hard
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="false" data-expert="true">
<div class="map-col">
Expert
</div>
</div>
<div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="false" data-expert="false">
<div class="map-col">
None
</div>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideEasyChkBox">Hide Easy</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideNormalChkBox">Hide Normal</label>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideHardChkBox">Hide Hard</label>
</div>
</div>
<div class="checkbox">
<label><input type="checkbox" id="hideExpertChkBox">Expert</label>
</div>
And js:
jQuery(document).ready(function ($) {
updateVisible = function () {
$("#elems>div.datadiv").each(function (index, value)
{
$(value).show();
if ($(value).attr("data-expert") === "true")
{
if ($("#hideExpertChkBox").is(':checked'))
{
$(value).hide();
}
}
if ($(value).attr("data-hard") === "true")
{
if ($("#hideHardChkBox").is(':checked'))
{
$(value).hide();
}
}
if ($(value).attr("data-normal") === "true")
{
if ($("#hideNormalChkBox").is(':checked'))
{
$(value).hide();
}
}
if ($(value).attr("data-easy") === "true")
{
if ($("#hideEasyChkBox").is(':checked'))
{
$(value).hide();
}
}
});
};
$(document).on("change", "#hideEasyChkBox", function () {
updateVisible();
});
$(document).on("change", "#hideNormalChkBox", function () {
updateVisible();
});
$(document).on("change", "#hideHardChkBox", function () {
updateVisible();
});
$(document).on("change", "#hideExpertChkBox", function () {
updateVisible();
});
});
So how it works - on checkbox change it call updateVisible() function. Than it get first div and show all it. After that it test if checkbox of filter checked and if div have atrr and if so, just hide it, if none attr set to true it just ingore such div. And then all repeated for all other divs.

How to get the ID of the Current element clicked

I want to get the Value of the Current Element to be clicked.
I have a list of Checkboxes and selection of each I want to get the ID of it which is hidden.
My Code goes as follows:
$("#ModelListView").on("click", ".ModelCheckBox", function (element) {
var AnalysisID = $("#AnalysisID").val();
var ModelID = '';
});
HTML:
<div id="ModelListView"></div>
<script type="text/x-kendo-template" id="Modeltemplate">
<div class="section group fr">
<div class="col span_2_of_12">
#if(ACTIVE_MODELS_COUNT > 0){# <input class="ModelCheckBox" type="checkbox" checked/>#} else {# <input class="ModelCheckBox" type="checkbox" unchecked/> #}#
</div>
<div class="col span_4_of_12"><label>#:MODEL#</label></div>
<input id="Model_ID" type="hidden" value=#:MODEL_ID#/>
</div>
</script>
I want to get the Value of Model_ID that is kept hidden.
You can use $(this) and get the closest.
$(this) will be the element that's clicked.
.closest('.section.group') will return the "section group"-div. You might want to use #ModelListView instead of .section.group.
.find('#Model_ID').val() will return the value of the hidden field.
$("#ModelListView").on("click", ".ModelCheckBox", function (element) {
var AnalysisID = $("#AnalysisID").val();
var ModelID = $(this).closest('.section.group').find('#Model_ID').val();
alert(ModelID);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ModelListView">
<div class="section group fr">
<div class="col span_2_of_12">
<input class="ModelCheckBox" type="checkbox" checked/>
</div>
<div class="col span_4_of_12"><label>Label</label></div>
<input id="Model_ID" type="hidden" value="someValue"/>
</div>
</div>
Sidenote: be aware of using an ID in a template.

How to enable disable a select drop down list using radio buttons with angularjs?

I have been searching all over for the internet looking on how to enable or disable this drop down list using radio buttons specifically when the radio button value is equal to prof the drop down list should be disabled, but with no help. I did come up with an example but didn't work. Any help would be appreciated.
registration.html
<div class="form-group">
<label class="col-lg-2 col-md-3 control-label">Qualification</label>
<div class="col-lg-10 col-md-9">
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="edu" name="radio1" id="radio4">
<label for="radio4">Educational</label>
</div>
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="prof" name="radio1" id="radio5">
<label for="radio5">professional</label>
</div>
</div>
</div>
//This is the drop down that I need to diable
<div class="form-group">
<label class="col-sm-2 control-label" for="Qulitype">Qualification type</label>
<div class="col-sm-10">
<select name="repeatSelect" id="repeatSelect" ng-disabled="QualificationDetails.qualification_type == 'prof'" ng-model="QualificationDetails.qualification" class="form-control">
<option ng-repeat="quali in qualiLevel" value="{{quali.qualification_id}}">{{quali.quali_level}}</option>
</select>
</div>
</div>
This is the code I implemented to work above scenario. But didn't work :(
regController.js
$scope.$watch('QualificationDetails.qualicication_type', function (QualiType) {
if (angular.isUndefined($scope.QualificationDetails)) {
return;
}
if (QualiType === 'prof') {
$scope.QualificationDetails.qualification_type = $scope.QualiType;
}
else {
if ($scope.QualificationDetails.qualification_type !== null) {
$scope.QualiType = $scope.QualificationDetails.qualification_type;
$scope.QualificationDetails.qualification_type = null;
}
}
});
the above scenario is that when it comes to qualifications if qualification type is equal to professional (prof) drop down list is disabled and when it is educational the drop down list should be enabled. Any idea on how to achieve this.
This is the Quality level json. I get it through the qualitylevel.service.
(function initController() {
deptService.getdepts(function (res) {
$scope.depts = JSON.parse(res.data);
});
qualiService.getquali(function (res) {
console.log("inside ");
$scope.qualiLevel = JSON.parse(res.data);
});
console.log("inside service");
})();
It seems to me, that your code works fine without watcher you have added. I hope I understood what you want correctly. Try this snippet:
angular
.module('app', [])
.controller('Ctrl', function($scope) {
$scope.qualiLevel = [
{quali_level: 'A', qualification_id: 1},
{quali_level: 'B', qualification_id: 2}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="Ctrl">
<div class="form-group">
<label class="col-lg-2 col-md-3 control-label">Qualification</label>
<div class="col-lg-10 col-md-9">
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="edu" name="radio1" id="radio4">
<label for="radio4">Educational</label>
</div>
<div class="radio-custom radio-inline">
<input type="radio" ng-model="QualificationDetails.qualification_type" value="prof" name="radio1" id="radio5">
<label for="radio5">professional</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="Qulitype">Qualification type</label>
<div class="col-sm-10">
<select name="repeatSelect" id="repeatSelect" ng-disabled="QualificationDetails.qualification_type == 'prof'" ng-model="QualificationDetails.qualification" class="form-control">
<option ng-repeat="quali in qualiLevel" value="{{quali.qualification_id}}">{{quali.quali_level}}</option>
</select>
</div>
</div>
</div>
</div>
As the control is radiobutton, your QualificationDetails.qualification_type value will be set to 1 or 0 and not to the label value. You have to have different variables for two radio buttons. Based on their value you have to set QualificationDetails.qualification_type = 'prof' or something
You can also try $parent.QualificationDetails.qualification_type instead as answered in How can I get the value of the checked radio button when submitting a form using angularjs?
Thanks everyone for helping me out. Just felt wanted to show I implemented it correctly and other programmers to increase their knowledge. Using $watch to temporaly hide the drop down list details).
the registrationController.js
$scope.$watch('QualificationDetails.qualification_type', function (Val) {
if (angular.isUndefined($scope.QualificationDetails))
return;
if (Val !== 'prof') {
$scope.QualificationDetails.qualification = $scope.tempValue;
}
else {
if ($scope.QualificationDetails.qualification !== null) {
$scope.tempValue = $scope.QualificationDetails.qualification;
$scope.QualificationDetails.qualification = null;
}
}
});
Implemented through this example.

Categories