Reputation: 15489
I'm on a angularjs application with jquery and can't seem to change the background color of some inputs. In short, when the user clicks "hide stage" text or "unhide stage" text, the input boxes background should change to white/lightgrey respectively. But the only thing that changes is the text between "hide stage" to "unhide stage" which is fine. Here is the angularjs file:
function stages($scope,$rootScope,$apiSrvc,$compile){
// defintions
// setting up stages statuses to angular array.
$scope.stages_visibilities = ['unhidden','unhidden','unhidden','unhidden','unhidden','unhidden','unhidden','unhidden'];
// changes the stage's status and it's visibility settings
$scope.setStageStatus = function(stageN,status){
$scope.stages_visibilities[stageN] = 'hidden';
if(status === 'unhide'){
$scope.stages_visibilities[stageN] = 'unhidden';
}
$scope.showStages();
};
// shows the stage rows.
$scope.showStages = function() {
// update(populate) the caption/value rows
$('#stages_rows').empty();
$nStages = parseInt($scope.nStages);
var stage_row = "";
for(var i=0; i < $nStages; i++){
stage_row += '<div class="stage_row">'+
'<input type="text" id="stage_caption_'+i+'" class="stg_caption" />'+
'<input type="number" id="stage_value_'+i+'" class="stg_val" />';
// show hide/unhide for this stage.
if($scope.stages_visibilities[i] === 'unhidden'){
stage_row += '<span id="stage_hide_unhide_'+i+'" class="hide_unhide_stg" ng-click="setStageStatus('+i+',\'hide\')">hide stage</span>';
// set row color to white.
$("#stage_caption_"+i).css("background-color","white");
$("#stage_value_"+i).css("background-color","white");
$("#stage_value_"+i).prop('disabled', false);
$("#stage_caption_"+i).prop('disabled', false);
}
else {
stage_row += '<span id="stage_hide_unhide_'+i+'" class="hide_unhide_stg" ng-click="setStageStatus('+i+',\'unhide\')">un-hide stage</span>';
// set row color to lightgrey.
$("#stage_caption_"+i).css("background-color","lightgrey");
$("#stage_value_"+i).css("background-color","lightgrey");
$("#stage_value_"+i).prop('disabled', true);
$("#stage_caption_"+i).prop('disabled', true);
}
stage_row += '</div>';
}
$("#stages_rows").append(stage_row);
// register new directives to angularjs
$compile($("#stages_rows").contents())($scope);
}
}
All the angular js pre-liminary stuff work fine, it's just that section of the code where it doesn't change the background colors of the input(#stage_caption_i and #stage_value_i) which is in the $scope.showStages function. I have no idea what is wrong.
Upvotes: 2
Views: 98
Reputation: 7194
Here is a more "Angular" approach to what you're trying to do. I would recommend setting aside your jQuery knowledge as it really should only be used in a very limited fashion in directives. As georgeawg mentioned you shouldn't do DOM manipulation in the controller. Rather you should modify the values of your model and then put all the view-specific stuff in the HTML.
A preferred method would be to make the hidden/visible status a property on the model, rather than maintaining a separate array with that data. Of course, you can still use an array, but then you have to write a method to check the value of the visibility in the corresponding array when you want to change a class or toggle the disabled status. Using a method like that will cause a lot of traffic between the controller and the view as the view calls back for each item. Probably not noticeable on a small sample like this, but could lead to performance issues on a larger view. Even if you are getting this data back from a database or some other storage on the back end you can still extend the model to include a visibility property on the client.
The id
values aren't needed, but I've included them to show how to use $index
in case you decide to go the route of storing visibility in a separate array. You could use the $index
value from the ng-repeat
to reference the proper element in the visibility array.
This separation of controller and view will help with long term maintainability and keep Angular and jQuery from stepping on each other as they both manipulate elements of the DOM.
angular.module('app', [])
.controller('ctrl', ($scope) => {
$scope.stages = [{
caption: 'Stage 0',
value: 0,
hidden: false
}, {
caption: 'Stage 1',
value: 1,
hidden: false
}, {
caption: 'Stage 2',
value: 2,
hidden: false
}, {
caption: 'Stage 3',
value: 3,
hidden: false
}, {
caption: 'Stage 4',
value: 4,
hidden: false
}, {
caption: 'Stage 5',
value: 5,
hidden: false
}, {
caption: 'Stage 6',
value: 6,
hidden: false
}, {
caption: 'Stage 7',
value: 7,
hidden: false
}];
// changes the stage's status and its visibility settings
$scope.setStageStatus = (stage) => {
stage.hidden = !stage.hidden;
};
});
.hidden {
background-color: lightgray;
}
.unhidden {
background-color: white;
}
.hide_unhide_stg {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="stage_row" ng-repeat="stage in stages">
<input type="text"
id="stage_caption_{{$index}}"
class="stg_caption"
ng-model="stage.caption"
ng-disabled="stage.hidden"
ng-class="{hidden: stage.hidden, unhidden: !stage.hidden}" />
<input type="number"
id="stage_value_{{$index}}"
class="stg_val"
ng-model="stage.value"
ng-disabled="stage.hidden"
ng-class="{hidden: stage.hidden, unhidden: !stage.hidden}" />
<span class="hide_unhide_stg"
ng-click="setStageStatus(stage)"><span ng-if="stage.hidden">un-</span>hide stage</span>
</div>
</div>
Upvotes: 1