Download button not responding to ng-disabled in angularjs - angularjs

I have a webpage which displays contents of a folder/directory upon clicking on it. If the contents of a folder has files, then download button is activated. If the contents of the folder is a directory, download button is inactive.
Here is my code that is supposed to make that work. But the Download button remains active all the time and never goes inactive. Can somebody point out where I'm going wrong ?
$scope.IsFile = function(filenames){
forEach(filenames, function(filename){
if(filename.indexOf(".zip") > 1|| filename.indexOf(".txt") >1 || filename.indexOf(".xml") > 1 ) {
return true;
}
else {
return false;
}
});
};
<div class="col-md-3" id="CTP Jobs">
<div ng-click="GetListOfFilesonCTP('/home/topas/rda_app/JOBS/')">
<a href="">
<h3>
JOBS <small> <span class="btn-group"
role="group">
<button type="button" class="btn btn-default" ng-disabled="IsFile(listOfFilesOnJobs)"
ng-click="download()">Download</button>
</span>
</small>
</h3>
</a>
</div>
<table class="table table-striped"
ng-init="GetListOfFilesonCTP('/home/topas/rda_app/JOBS')">
<tr ng-repeat="jobs in listOfFilesOnJobs"
ng-click="GetListOfFilesonCTP(getPath('/home/topas/rda_app/JOBS/', jobs))">
<!--'/home/topas/rda_app/JOBS/'+ jobs + '/' -->
<td>{{jobs}}</td>
</tr>
</table>
</div>

Your IsFile function does not return anything explicitly (i.e. it returns undefined) and ng-disabled interprets that as false. The return true and return false on lines 4 and 7 are relative to the function passed to forEach, which is probably not what you want. Did you mean to filter the list of files and check if any files are remaining? Something like this would do:
$scope.isFile = function(filenames) {
return filenames.filter(function(filename) {
return filename.indexOf(".zip") > 1 ||
filename.indexOf(".txt") > 1 ||
filename.indexOf(".xml") > 1
}).length > 0
}

Related

Angularjs required validator for array in model

I have an array of 'bikes' that is required to be populated in my form (minimum length of 1). In my controller I have an empty array 'this.bikes = [];'
I have some controls which add and remove bikes from the array.
addBike(bike){
this.bikes.push(bike);
this.currentBike = null;
}
removeBike(bike){
this.bikes = this.bikes.filter((b) => bike != b);
}
How do I apply form validation on the array itself so that my form shows invalid if the array is empty (Something like 'if ($ctrl.bikes.length == 0) $ctrl.form.bikes.$valid = false)?
<label for="bike-make-model">Enter make and model of bike</label>
<div class="input-group p-relative">
<input name="bikeMakeModel" type="text" ng-model="$ctrl.currentBike" class="form-control" id="bike-make-model">
<span class="input-group-btn ">
<button class="btn btn-default" ng-click="$ctrl.addBike($ctrl.currentBike)" ng-disabled="!$ctrl.currentBike">ADD</button>
</span>
</div>
</div>
<div class="list-group" ng-show="$ctrl.bikes.length > 0">
<ul>
<li class="list-group-item" ng-repeat="bike in $ctrl.bikes">
<span>{{bike}} </span>
<i ng-click="$ctrl.removeBike(bike)" class="pointer pull-right far fa-trash-alt"/>
</li>
</ul>
</div>
I want to use it for to disable my submit button using the ng-disabled directive.
<button class="btn btn-primary" ng-disabled="!$ctrl.form.$valid" ng-click="$ctrl.continue()">Next</button>
Have you tried
<button class="btn btn-primary" ng-disabled="!$ctrl.form.$valid || $ctrl.bikes.length==0" ng-click="$ctrl.continue()">Next</button>
or you could add a variable in your script to monitor the length of the array. Say
addBike(bike){
this.bikes.push(bike);
this.currentBike = null;
this.bikesArrayLength = this.bikes.length;
}
removeBike(bike){
this.bikes = this.bikes.filter((b) => bike != b);
this.bikesArrayLength = this.bikes.length;
}
and in your button do
<button class="btn btn-primary" ng-disabled="!$ctrl.form.$valid || $ctrl.bikesArrayLength==0" ng-click="$ctrl.continue()">Next</button>
You can use directive for this purpose. Make a directive and in link function define the logic , if the array is empty make form invalid and it won't submit, your code is short that is why , i can't do it for you.
This is angular way to solve your problem. All i can do now is provide the logic or give you idea how this will go down.
.directive("dirName",function(){
return {
require: "ngModel",
scope: {
confirmArrayLength: "="
},
link: function(scope, element, attributes, modelVal) {
modelVal.$validators.dirName= function(val) {
return "your logic to check if array is empty or not!"
};
// and $watch function will validate and invalidate on the basis of return value of above function
scope.$watch("confirmArrayLength", function() {
modelVal.$validate();
});
}//link ends here
};//return ends here})
If this is the solution of your problem then accept this answer so that this thread can be close, thanks. And if you need any further assistance then feel free to ask.

How to bind a part of a variable already binded

I have a loop ng-repeat that displays sevral icons.
<div class="box">
<div class="box-body">
<div class="row" >
<div class="col-sm-6" style="margin-bottom: 5px;" ng-repeat="record in newlayout.display" align="center">
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
<span class="badge bg-yellow" style="font-size:22px;">{{record.numberOfSamples}}</span>
<i class="fa fa-{{newlayout.labStyle}}"></i> {{record.lab}}
</a>
</div>
</div>
</div>
</div>
My issue is that the second part of the binded variable itemValue should be dynamic
In my Js, I have this
newLayout.url = 'sublabs/?labName=';
newLayout.itemValue = 'record.lab';
The URL is dynamic.
When I click on the first displayed Icon, the url should look like this :
But it didn't work as I had a compilation error..
Does someone have an idea how to fix this:
http://localhost:8181/#/newlayout/sublabs?labName=PIA/C1 - Shiftlabo
Where the record value "PIA/C1 - Shiftlabo" change.
So basically here if I change
<a class="btn btn-app" ng-href="#newlayout/{{newlayout.url}}{{newlayout.itemValue}}" >
{{newlayout.itemValue}} by {{record.lab}} it would work..but the {{record.**lab**}} should be dynamic as it will have another value when I click on the icon. It will change to {{record.subLab}}
Thanks
Use property acccessor bracket notation inside the binding:
<div>{{record[labOrSublab]}}</div>
JS
var isSublab = false;
$scope.labOrSublab = "lab";
$scope.clickHandler = function() {
isSublab = !isSublab;
$scope.labOrSublab = isSublab ? 'subLab' : 'lab';
};

Protractor Locating elements by by.repeater contained within a specific div

In protractor, I am trying to access the buttons repeated withina specific div with id 'CreateRFQID'. These buttons are defined a directive 'gps-button-bar'. I am trying to access them by.repeater. Because these buttons also appear else where in the page, I can not just access them through
element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index')).
But I am trying without success to get those buttons that are sub element of the div with id 'CreateRFQID'.
Protractor code I am trying:
var parent = element(by.css('#CreateRFQID'));
var first= parent.element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index')).row(0);
first.getText().then(function (text) {
console.log(text);
});
Any help how to get it?
Thanks.
View / html Fragment
<div ng-controller="CreateRFQController as createRFQCntrl" id="CreateRFQID" class="ng-scope">
<gps-button-bar config="createRFQCntrl.buttonBarConfig" class="ng-isolate-scope"><div class="container-fluid">
<div class="row row-buttonBar">
<label><h1 class="panel-title ng-binding">RFQ Create </h1></label>
<span class="pull-right">
<span ng-repeat="aBtn in buttonBarController.config.buttonConfigs track by $index" style="padding-right: 2px" class="ng-scope">
<button class="btn btn-default btn-xs ng-binding" id=""myButton"+$index" ng-click="buttonBarController.clickHandler($index);" data-toggle="tooltip" data-placement="top" title="Create" ng-show="buttonBarController.gpsShownButtons[$index]" ng-disabled="buttonBarController.gpsDisabledButtons[$index]">
<span class="fa fa-floppy-o"></span> Create
</button>
</span><!-- end ngRepeat: aBtn in buttonBarController.config.buttonConfigs track by $index -->
</span>
</div>
You have a problem in the selector, you don't do .row on the result of element but on the by
var parent = element(by.id('CreateRFQID'));
var first = parent.element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index').row(0));
first.getText().then(function (text) {
console.log(text);
});

AngularJS ng-if doesn't show the DIV

Why my app isn't working properly? It must show one (one at time) of the div on the bottom with the "ng-if" tag..
This is the fiddle:
Fiddle
<div class="fix" ng-if="showAdd()">
<button type="button" class="btn btn-link">
<span class="glyphicon glyphicon-plus"></span>
<span class="fix">Aggiungi un Preferito</span>
</button>
<div class="add">
Aggiungi un Preferito
</div>
</div>
<div class="edit" ng-if="showEdit()">
Modifica
</div>
The problem is with the showEdit() function.
From your fiddle you have:
function showEdit() {
return $scope.startEdit && !$scope.startAdd;
}
Where startEdit and startAdd are defined as:
function startAdd() {
$scope.addBookmark = true;
$scope.editBookmark = false;
}
function startEdit() {
$scope.editBookmark = true;
$scope.addBookmark = false;
}
When your ng-if calls showEdit() it will return $scope.startEdit && !$scope.startAdd;
However, $scope.startEdit and $scope.startAdd are functions, so they will be "truthy" (i.e. evaluate to true in a boolean expression). Therefore, the boolean expression always evaluates to false (and your DIV remains hidden).
See below:
$scope.startEdit && !$scope.startAdd;
true && !true
true && false
false
It looks like you're missing something conceptually with either calling functions or with evaluating boolean expressions.
If you want to call a JavaScript function, you have to follow the name of the function with parenthesis, just like you did with your ng-if="showEdit()" block.
Similarly, if $scope.showEdit() is meant to call startAdd() and startEdit(), you should do something like this:
function showEdit() {
return $scope.startEdit() && !$scope.startAdd();
}
You'd still have a problem, however, as startEdit() and startAdd() don't return anything, and would therefore evaluate to undefined.
If you edit your showEdit() function as described above and have startEdit() and startAdd() return a boolean expression, you should be good to go.
It looks like there's a mistake in your fiddle. The edit div will show up if you change your showAdd and showEdit methods to the following:
function showAdd() {
return $scope.addBookmark && !$scope.editBookmark;
}
function showEdit() {
return $scope.editBookmark && !$scope.addBookmark;
}
The add div never gets added because that would be activated by the startAdd function, which isn't called anywhere.
Also, please post your javascript code here. That way, if something happens to your fiddle, this question might still be useful to others.
EDIT:
To get your add button to work you need to change this:
<div class="fix" ng-if="showAdd()">
<button type="button" class="btn btn-link">
<span class="glyphicon glyphicon-plus"></span>
<span class="fix">Aggiungi un Preferito</span>
</button>
<div class="add">
Aggiungi un Preferito
</div>
</div>
To this:
<button type="button" class="btn btn-link" ng-click="startAdd()">
<span class="glyphicon glyphicon-plus"></span>
<span class="fix">Aggiungi un Preferito</span>
</button>
<div class="fix" ng-if="showAdd()">
<div class="add">
Aggiungi un Preferito
</div>
</div>
If the desire is to always show one or the other, then it is best practice to structure the view as follows:
<div class="fix" ng-if="showingAdd">
<button type="button" class="btn btn-link">
<span class="glyphicon glyphicon-plus"></span>
<span class="fix">Aggiungi un Preferito</span>
</button>
<div class="add">
Aggiungi un Preferito
</div>
</div>
<div class="edit" ng-if="!showingAdd">
Modifica
</div>

Angularjs: how change icon when item is clicked

I know that this question has already some answers/solutions but none of them works for me most probably because this is the first time when I'm trying to implement something using Angularjs.
I have a div (title) that expands some info when it's clicked and I want to change the icon inside of it when that info is visible...
This is my code:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right"></i>
</div>
And this is what I tried to do, but not working because the div will not show the expanded info anymore:
<div class="title" ng-click="view_variables(request) = !view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!view_variables(request), 'glyphicon glyphicon-chevron-left': view_variables(request)}"></i>
</div>
Controller code:
$scope.view_variables = function(req){
if (!req.enabled_variables && !req.disabled_variables) {
$http.get('/api/files/' + $scope.file_id + '/requests/' + req.id + '/variables')
.success(function(data){
variables = data.data;
req.enabled_variables = [];
req.disabled_variables = [];
for (i=0; i<variables.length; i++) {
if (variables[i].disabled == true) {
req.disabled_variables.push(variables[i]);
} else {
req.enabled_variables.push(variables[i])
}
}
});
}
req.show_variables = !req.show_variables;
}
The view_variables function doesn't return anything, so it will always be treated as false.
You want something like this:
<div class="title" ng-click="view_variables(request)">
<i ng-class="{'glyphicon glyphicon-chevron-right':!request.show_variables, 'glyphicon glyphicon-chevron-left': request.show_variables}"></i>
</div>
I think the problem is what you have going on in the ng-click attribute. By using "view_variables(request) = !view_variables(request)" are you not calling the view_variables function twice? Also, it seems strange to be assigning a value to a function call.
I would just keep ng-click="view_variables(request)" as you had in the first line of code, then have the view_variables function set a boolean somewhere in scope ($scope.data.view_vars) and have that determine ng-class for your i element.
Good luck!
--EDIT: Now that you've put up your controller, req.show_variables looks like a useful candidate
Calling a function inside ng-class is a bad idea. Why don't you use a flag for it.
eg.
inside controller-
$scope.view_variables = function(request){
//your code
$scope.isExpanded = !$scope.isExpanded;
};
and in html
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon" ng-class="{'glyphicon-chevron-right':!isExpanded, 'glyphicon-chevron-left':isExpanded}"></i>
</div>
May be Better this way using ng-show directive:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-show="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-show="view_variables(request)"></i>
</div>
You could use ng-if directive like so:
<div class="title" ng-click="view_variables(request)">
<i class="glyphicon glyphicon-chevron-right" ng-if="!view_variables(request)"></i>
<i class="glyphicon glyphicon-chevron-left" ng-if="view_variables(request)"></i>
</div>
assuming view_variables(request) returns true or false... maybe could replace it for req.show_variables.

Resources