Showing discard and save buttons when objects aren't equal - angularjs

In the controlller I have this code when the template loads:
$scope.pristine_timesheet = angular.copy($scope.timesheet);
In the template I want to do this:
<div ng-show="(timesheet != pristine_timesheet)">
<div class="button-bar">
<a class="button button-positive" ng-click="update(form)">Save changes</a>
<a class="button button-stable" ng-click="discard(form)">Discard changes</a>
</div>
</div>
For some reason this is always showing the buttons. I know I could use $dirty but wondering why this isn't working.

I solved it by extending the class in the service like this:
angular.extend(Timesheet.prototype, {
compare: function(timesheet){
return ((timesheet.id == this.id) && (timesheet.notes == this.notes) && (timesheet.task_link_id == this.task_link_id) && (timesheet.time_start == this.time_start) && (timesheet.time_end == this.time_end));
}
In the template I can now simply do:
<div ng-show="!(timesheet.compare(pristine_timesheet))">
Thanks PSL for the explanation. I also tried with lodash isEqual but that one didn't work for me: https://lodash.com/docs#isEqual

Related

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 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.

ng-click odd behavior when using "var = !var"

<accordion class="nested-accordion">
<accordion-group ng-repeat="item in menu" is-open="item.opened" ng-if="item.children == true && item.grandchild == true">
<accordion-heading id="inner-accordion">
---- PROBLEM HERE ----
<div ng-click="item.opened = !item.opened" class="toggle-caret">
<span class="glyphicon glyphicon-play" ng-class="{true: 'caret-open', false:'caret-closed'}[item.opened]"></span>
</div>
<button class="btn-link filter-option" ng-class="{true:'option-checked', false:''}[item.checked]" ng-click="test(item, $event); $event.stopPropagation()">{{item.name}}</button>
</accordion-heading>
<div>
<!-- some stuff here -->
</div>
</accordion-group>
</accordion>
I am having an issue with the line I singled out in the code above. The ng-click is not toggling the item.opened from true to false. However, if I change the syntax from:
ng-click="item.opened = !item.opened"
to:
ng-click="item.opened != item.opened"
the accordion works as expected. This is not what I want though.
Further more this is the only part out of the accordion that is experiencing this issue. Can anyone explain why this is giving me a hard time?

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>

Resources