AngularJS ng-if doesn't show the DIV - angularjs

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>

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';
};

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.

Angularjs if/else statements

<div class="company_name" ng-controller="CompanyName">
<h1 class="left">
{{data.company_name}}
</h1>
</div>
What I'd like to do is make it so that if data.company_name hasn't been added through an input field, it shows a placeholder "Company name", how can that be done using angularjs?
You can use ng-if and do something like
<div class="company_name" ng-controller="CompanyName">
<h1 class="left">
<span ng-if="data.company_name === ''">
// Some placeholder
</span>
<span ng-if="data.company_name !== ''">
{{data.company_name}}
</span>
</h1>
</div>
BTW ngIf is a new directive added in v1.1.5 so you might need to upgrade your angular version
See my plunker here : http://plnkr.co/edit/qiN2XshEpay6e6zzhUKP
One way to keep the code clean is to use a filter. This piece of code adds a class to an active tab.
var filters = angular.module('filters');
filters.filter('ie', function(){
return function(v, yes, no){
return v ? yes : no;
};
});
Template
<li class="{{activeTab == 'home' | ie: 'active-class':''}}">
Home
</li>
For Using ng-if, ng-else-if, and ng-else in your project use this:
https://github.com/zachsnow/ng-elif
You can use ng-if condition for the check company name vlaue. Let's take example of
<span ng-if="driver.status_flag == 1">
<i ngif="{{driver.status_flag}}" class="icon-ok-sign icon-2x link" style="color:#090" href="#" title="Payment received" ></i>
</span>
In above example I have added condition status_flag value is 1 then the inside span value will show. Same way with your case you can add statement like
<span ng-if="data.company_name === ''">
<i ngif="{{driver.status_flag}}" class="icon-ok-sign icon-2x link" style="color:#090" href="#" title="Payment received" ></i>
</span>

Conditional ng-include in angularjs

How can I do the ng-include conditionally in angularJS?
For example I only want to include something if, the variable x is set to true.
<div ng-include="/partial.html"></div>
If you are using Angular v1.1.5 or later, you can also use ng-if:
<div ng-if="x" ng-include="'/partial.html'"></div>
If you have any older version:
Use ng-switch:
<div ng-switch on="x">
<div ng-switch-when="true" ng-include="'/partial.html'"></div>
</div>
Fiddle
You could also do
<div ng-include="getInclude()"></div>
In your controller
$scope.getInclude = function(){
if(x){
return "partial.html";
}
return "";
}
A little bit more readable version of one of the answers. Plus setting ng-include to null removes the element - just like ng-if.
<div ng-include="x ? 'true-partial.html' : null"></div>
If the condition is simple enough, you could also put the conditional logic directly in the ng-include expression:
<div ng-include="x && 'true-partial.html' || 'false-partial.html'"></div>
Note the expression x is not in single quotes and therefore evaluated. See http://plnkr.co/edit/4fvNDa6Gm3dbVLgsAZrA for more details.
I encountered a similar issue and may be this finding can help someone. I have to display different partials on click of link but ng-if and ng-switch both were not working in this scenario(Below code was not working).
<button type="button" class="btn btn-link" ng-click="viewType('LIST')">List All</button>
<button type="button" class="btn btn-link" ng-click="viewType('EDIT')">Edit</button>
<button type="button" class="btn btn-link" ng-click="viewType('VIEW')">View</button>
<section class="col-md-8 left-col">
<span ng-if = "LIST">
<div data-ng-include="'./app/view/articles/listarticle.html'">
</span>
<span ng-if = "EDIT">
<div data-ng-include="'./app/view/articles/editorarticle.html'">
</span>
</section>
So what I did is, instead of using ng-if, On click of link just update the value of partialArticleUrl (which is a model in controller) and declare below code on html.
<section class="col-md-8 left-col">
<div data-ng-include="partialArticleUrl">
</section>

Resources