I have such an div element:
<div className="rate" >
<mark className="rate-mark"> Rate : </mark>
<mark className="val-mark" style={{color}}> {rate}</mark>
</div>
where the color is a hook:
var green = "#0cb87f";
var red = "#ce2020";
const [color,setColor] = useState(green)
I'm trying to dynamically change the color like this :
if (response.getRate() < rate){
setColor(red)
}else{
setColor(green)
}
But in my case it turns out that the light is always green.I think the mark page element is just never updated.How can this be made to work?
I'm trying to toggle disabled status of several element using one button. I did function which only toggle status of one element.
Disabled() {
var element = <HTMLInputElement>document.getElementById("input");
if (element.disabled == true) {
element.disabled = false;
} else {
element.disabled = true;
}
}
what should I change to make it work?
You can bind the input's disabled property to a variable in your code and change that variable on click:
<input ng-disabled="disabled"/>
<button ng-click="disabled = !disabled">
Disable
</button>
Example: https://stackblitz.com/edit/angularjs-n78yrt?file=home%2Fhome.html
Update: Stackblitz changed to work without ng-syntax
I have a select with ngOptions based on an array. This array can change.
If the new array value does not contain the selected option value, the option value is set to undefined by the selectController. Is there a way to prevent this ?
Plunker : https://plnkr.co/edit/kao3h5ivHXlP1Wrdx1Ib?p=preview
Scenario:
select Blue/Red or Green color
click on Reduced to only have Black and White options
See that the model value is left to blank
Wanted behavior : that the model value stays at Blue/Red or Green
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
</head>
<body ng-app="selectExample">
<script>
angular.module('selectExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.colorsFull = [
{id:"bk", name:'black'},
{id:"w", name:'white'},
{id:"r", name:'red'},
{id:"be", name:'blue'},
{id:"y", name:'yellow'}
];
$scope.colors = $scope.colorsFull;
$scope.selectedColor =$scope.colorsFull[0];
$scope.colorsReduced = [
{id:"bk", name:'black2'},
{id:"w", name:'white2'}];
}]);
</script>
<div ng-controller="ExampleController">
<button ng-click="colors=colorsReduced">Reduced</button>
<button ng-click="colors=colorsFull">Full</button>
<br/>
Colors : {{colors}}
<hr/>
<select ng-model="selectedColor" ng-options="color.name for color in colors track by color.id">
</select>
selectedColor:{{selectedColor}}
</div>
</body>
</html>
You can achieve this by keeping track of what color is selected in the full colors dropdown, and inserting it into the reduced colors array. First, add an ng-change directive so that we can keep track of the selected color:
<select ng-model="selectedColor" ng-options="color.name for color in colors track by color.id" ng-change="setColor(selectedColor)">
And in your controller:
$scope.setColor = function(color) {
if(color !== null) {
// Keep track of the color that is selected
$scope.previousColor = color;
}
else {
// Changed arrays, keep selected color in model
$scope.selectedColor = $scope.previousColor;
}
}
Now ng-model is set to the correct color whenever the arrays are changed, but it will appear blank in the reduced colors dropdown because the option doesn't exist. So, we need to insert that option into the array. However, switching back and forth between dropdowns will cause the reduced colors array to keep on adding more options, and we only want to remember the option we selected from the full colors array. So, we need create an initial set of colors to revert back to when switching.
// Keep a copy of the original set of reduced colors
$scope.colorsReducedInitial = [
{id:"bk", name:'black2'},
{id:"w", name:'white2'}];
Finally, we need to insert the selected option into the reduced colors array. Change the ng-click on the Reduced button to use a function:
<button ng-click="setColorsReduced()">Reduced</button>
Now, we can insert the option, after resetting the reduced colors array to its initial state:
$scope.setColorsReduced = function() {
// Revert back to the initial set of reduced colors
$scope.colors = angular.copy($scope.colorsReducedInitial);
if($scope.previousColor !== undefined) {
var found = false;
angular.forEach($scope.colorsReducedInitial, function(value, key) {
if(value.id == $scope.previousColor.id) {
found = true;
}
});
// If the id is found, no need to push the previousColor
if(!found) {
$scope.colors.push($scope.previousColor);
}
}
}
Note that we are looping through the reduced colors array to ensure we aren't duplicating any colors, such as black or white.
Now, the reduced colors ng-model has the previous dropdown's selected color.
Updated Plunkr Demo
Use below code in script
$scope.makeSelected=function(){
$scope.selectedColor =$scope.colorsReduced[0];
}
And just add this function call in reduced button line like below
<button ng-click="colors=colorsReduced;makeSelected()">Reduced</button>
This will do what you want to achieve.
Using Jukebox's answer, I ended-up writing a directive, using the modelCtrl.$formatters to get the initial value. It also offer the possibility to store the previousValue in the scope or in a local variable :
Usage: <select .... select-keep> or <select .... select-keep="previousColor">
Directive:
.directive('selectKeep', function($parse) {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
var previousValueGetter;
var previousValueSetter;
if (attrs.selectKeep) { //use a scope attribute to store the previousValue
previousValueGetter = $parse(attrs.selectKeep);
previousValueSetter = previousValueGetter.assign;
}
else { //use a local variable to store the previousValue
var previousValue;
previousValueGetter = function(s) { return previousValue;};
previousValueSetter = function(s, v) { previousValue = v;};
}
//store the initial value
modelCtrl.$formatters.push(function(v) {
previousValueSetter(scope, v);
return v;
});
//get notified of model changes (copied from Jukebox's answer)
modelCtrl.$viewChangeListeners.push(function() {
if (modelCtrl.$modelValue !== null) {
previousValueSetter(scope, modelCtrl.$modelValue);
} else {
modelCtrl.$setViewValue(previousValueGetter(scope));
}
});
}
};
Plunker
Edit : it has a flaw, the form gets dirty even if the value does not change. I had to add these lines in the else of the viewChangeListener but it doesn't look nice. Any ideas ?:
...
} else {
modelCtrl.$setViewValue(previousValueGetter(scope));
//set pristine since this change is not a real change
modelCtrl.$setPristine(true);
//check if any other modelCtrl is dirty. If not, we will have to put the form as pristine too
var oneDirty =_.findKey(modelCtrl.$$parentForm, function(otherModelCtrl) {
return otherModelCtrl && otherModelCtrl.hasOwnProperty('$modelValue') && otherModelCtrl !== modelCtrl && otherModelCtrl.$dirty;
});
if (!oneDirty) {
modelCtrl.$$parentForm.$setPristine(true);
}
}
I have a tooltip working on a glyphicon. When I click on the glyphicon I want to hide the tooltip, and then change the text of the tooltip. This reflects a change in state for the glyphicon which has been clicked.
However, when I hide the tooltip and then change the text of the tooltip, instead of doing it in this order, for a second you can see the new text in the tooltip before it disappears.
Here is the html:
<span class="glyphicon glyphicon-eye-open watch-eye"
ng-click="eyeClicked()" uib-tooltip="{{watchTooltip}}"
tooltip-placement="auto top" tooltip-is-open="eyeTooltipIsOpen">
</span>
And here is javascript:
$scope.watchingCategory = false;
$scope.watchTooltip = 'Watch';
$scope.eyeClicked = function() {
$scope.eyeTooltipIsOpen = !$scope.eyeTooltipIsOpen;
$scope.watchingCategory = !$scope.watchingCategory;
if($scope.watchingCategory === true) {
$scope.watchTooltip = 'Dont watch';
}
else if($scope.watchingCategory === false) {
$scope.watchTooltip = 'Watch';
}
};
I've created a plnkr to show exactly how it is working: http://plnkr.co/edit/myQlkkiSNO14td21Dv0M
Any ideas how to stop this behaviour? All help appreciated...
This is probably a problem whitin the uib directive.
A timeout solves the problem :
$timeout(function(){
$scope.watchTooltip = $scope.watchingCategory ? 'Dont watch' : 'Watch';
}, 200);
http://plnkr.co/edit/myQlkkiSNO14td21Dv0M?p=preview
We're trying to implement a checkbox and list with the following functionality:
Clicking the checkbox will either clear the array if there are items in there, or add a new item if not.
Remove an item from the array when clicking the Remove button, once the last item is removed the checkbox automatically unchecks itself.
The problem I am having is that if you click to remove each array item, then click the checkbox to add a blank entry, I'm expecting the checkbox to be checked again (as per the checked observable), however it is not?
I have the following code:
http://jsfiddle.net/UBsW5/3/
<div>
<input type="checkbox" data-bind="checked: PreviousSurnames().length > 0, click: $root.PreviousSurnames_Click" />Previous Surname(s)?
</div>
<div data-bind="foreach: PreviousSurnames">
<div>
<input type="text" data-bind="value: $data">
<span data-bind="click: $root.removePreviousSurname">Remove</span>
</div>
</div>
var myViewModelExample = function () {
var self = this;
self.PreviousSurnames = ko.observableArray(['SURNAME1', 'SURNAME2', 'SURNAME3']);
self.removePreviousSurname = function (surname) {
self.PreviousSurnames.remove(surname);
};
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
alet(2)
}
}
ko.applyBindings(new myViewModelExample());
If you are using together the click and the checked then you need to return true from your click handler to allow the browser default click action which is in this case checking the checkbox:
self.PreviousSurnames_Click = function () {
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
}
else {
self.PreviousSurnames.removeAll();
}
return true;
}
Demo JSFiddle.
You need to use a computed to monitor the length of the observable array. This way when the length reaches zero you can react to it automatically.
self.surnames = ko.computed(function() {
var checked = true;
if (self.PreviousSurnames().length === 0) {
self.PreviousSurnames.push('');
checked = false;
}
return checked;
});
Now you will have the blank text box when all of the names are cleared. If you update your binding on the checkbox it will function properly as well.
<input type="checkbox" data-bind="checked: surnames, click: PreviousSurnames_Click" />Previous Surname(s)?
FIDDLE