angular Way of: show or hide element after button click - javascript

I am pretty new to angular and i cant get it right.
inside the following example i am trying to show the answer to a question after the user clicks on the corresponding button.
before the answer is shown i want to run a function that checks if the user has the privilege to reveal the answer. in the example i assume he has the rights.
what i have to do to to remove the "ng-hide" class in the row where the button was clicked.
i appreciate any kind of help.
thanks in advance
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
["what is 1+1?"],
["what color of the sky"],
["what is the answer to the universe"]
];
$scope.answers = [
2, ["blue, black or orange"],
40
];
$scope.hideme = function(i) {
$log.log("element " + i + " was cicked");
//this will be detemined within a fct, so lets asume the has the according rights
var userPrivilege = true;
if (userPrivilege) {
//HOW TO: show the answer with the index i
}
}
}]);
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<!-- angular -->
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<script src="app.js"></script>
<!-- jquery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body ng-controller=QuestionCtlr>
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions track by $index">
<td>{{q[0]}}</td>
<td class = "ng-hide">{{q[0]}}</td>
<td>
<button type="button" ng-click="hideme($index)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Here's a complete working example.
Things I changed:
The answers are now stored as a property of each question. This makes the code neater (no need to track by $index).
The ng-show directive is used as an attribute instead of a class, and is bound to a showAnswers property of the question.
The showme function sets the showAnswers property to true when you click the button.
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
{question: "what is 1+1?", answers: [2]},
{question: "what color of the sky", answers: ["blue", "black", "orange"]},
{question: "what is the answer to the universe", answers: [42]}
];
$scope.showme = function(q) {
$log.log("question " + q.question + " was cicked");
var userPrivilege = true;
if (userPrivilege) {
q.showAnswers = true;
}
}
}]);
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<!-- angular -->
<script src="https://code.angularjs.org/1.4.0/angular.min.js"></script>
<script src="app.js"></script>
<!-- jquery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body ng-controller=QuestionCtlr>
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th colspan="2">Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions">
<td >{{q.question}}</td>
<td ng-show="q.showAnswers">
<div ng-repeat="a in q.answers">{{a}}</div>
</td>
<td>
<button type="button" ng-click="showme(q)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>

Try in html
<table class="table table-hover">
<thead>
<tr>
<th>Question</th>
<th>Answer</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="q in questions">
<td>{{q[0]}}</td>
<td ng-class="{hide : active != $index}">{{answers[$index]}}</td>
<td>
<button type="button" ng-click="hideme($index)" class="btn btn-default">show me</button>
</td>
</tr>
</tbody>
</table>
angular
var myApp = angular.module('myApp', []);
myApp.controller('QuestionCtlr', ['$scope', '$log', function($scope, $log) {
$scope.questions = [
["what is 1+1?"],
["what color of the sky"],
["what is the answer to the universe"]
];
$scope.answers = [
2, ["blue, black or orange"],
40
];
$scope.active = null;
$scope.hideme = function(i) {
$scope.active = i;
}
}]);
Fiddle

Taking your 'privilege' request in consideration, I think you will want to create a condition. Instead of adding the class ng-hide, use ng-hide, ng-show or ng-if like this:
<td ng-show="hasPrivilege && show[$index]">
<!--or ng-hide or ng-if-->
and your button:
<button type="button" ng-click="hideme($index)">
This will show the td if both statements are true. If one or both of them are false, it won't show the element.
then in your controller:
$scope.hideme = function(index) {
$scope.hasPrivilege = getPrivilege();
$scope.show[index] = true;
}
the getPrivilege() function should return true or false based on whether the user has the privilege.

Okay first of all you can use
ng-if="condition" //gets only rendered if condition is true
ng-show="condition" //shows when condition is true
ng-hide="condition" //hides when condition is true
So on your button
ng-click="showAnswer()"
In your Controller
$scope.displayAnswer = false;
$scope.showAnswer = function(){
if(hasRights == true){
$scope.displayAnswer = true //this is used for the hide and show
}
}
In your html 3 possible ways
<span ng-if="displayAnswer == true">This is the answer!!!</span>
<span ng-show="displayAnswer == true">This is the answer!!!</span>
<span ng-hide="displayAnswer == false">This is the answer!!!</span>
<button ng-click="showAnswer()">This is the answer!!!</span>
2nd Solution with toggle
if you want to hide the Answer again on the same button
This shows and hides the button depending if its currently shown or hidden
$scope.toggleAnswer = function(displayAnswer){
if(hasRights == true && $scope.displayAnswer == false){
$scope.displayAnswer = true //this is used for the hide and show
}else if($scope.displayAnswer == true){
$scope.displayAnswer = false;
}
}
2nd Html
<span ng-if="displayAnswer == true">This is the answer!!!</span>
<button ng-click="toggleAnswer(displayAnswer)">This is the answer!!!</span>
In your case
<button ng-click="toggleAnswer($index)">Hide / Show</button>
And In your Controller
$scope.answers = [{A: 2, show: false},{A: 'blue', show: false}]
$scope.toggleAnswer = function(index){
if(hasRights == true){
$scope.answers[index].show = true //this is used for the hide and show
}
}
in HTML
<span ng-if="item.show == true">The Answer !!</span>
//the item is coming from item in Answers from the ng-repeat

Related

angular js ng-click ng-controller and ng-app

I can't get angularJS to recognize a variable defined in ng-app, ng-controller, or ng-click.
3 sets of codes that I tried so far are:
<table>
<thead>
<tr>
<script>
var app = angular.module('ngClickApp', []);
app.controller('ngClickCtrl', function ($scope) {
$scope.clkCount = 0;
});
</script>
<th ng-app="ngClickApp" ng-controller="ngClickCtrl">
<button class="some-scss" ng-click="clkCount = clkCount +1">
<b>someCol {{ clkCount }}</b>
</button>
</th>
<table>
<thead>
<tr ng-app="ngClickApp">
<th><button class="some-scss" ng-controller="ngClickCtrl"><b>someCol {{ clkCount }}</b></button></th>
<script>
var app = angular.module('ngClickApp', []);
app.controller('ngClickCtrl', function ($scope) {
$scope.clkCount = 0;
});
</script>
<table>
<thead>
<tr ng-app="ngClickApp">
<th><button class="some-scss" ng-controller="ngClickCtrl"><b>someCol {{ clkCount }}</b></button></th>
<script>
var ngClickCtrl = function ($scope) {
$scope.clkCount = 0;
};
</script>
All three of them failed to recognize clkCount.
Examples that I found do not use table format. (https://www.tutorialsteacher.com/angularjs/angularjs-scope) or (https://www.tutlane.com/tutorial/angularjs/angularjs-ng-click-event-function-with-example)
Also, just out of curiosity, to test ng-click in the first code, I defined some function and called it in ng-click, but it did not work.
clickTest() {
console.log('1');
}
<th><button class="some-scss" ng-click="clickTest()">someButton</button></th>
did not print 1 when I clicked "someButton" whereas
clickTest() {
console.log('1');
}
<th><button class="some-scss" (click)="clickTest()">someButton</button></th>
did print 1 when I clicked the same button.
So, I was wondering if ng-app, ng-controller, and ng-click need some type of initiation or they have to be in the <tbody> or any other suggestions why all the above codes that worked just fine in examples do not work in the tables.
<!DOCTYPE html>
<html lang="en-US">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<table>
<thead>
<tr ng-app="ngClickApp">
<th>
<button class="some-scss" ng-controller="ngClickCtrl" ng-click="clkCount=clkCount+1"><b>someCol {{clkCount}}</b></button>
</th>
</tr>
</thead>
</table>
</body>
</html>
<script>
var app = angular.module('ngClickApp', []);
app.controller('ngClickCtrl', function ($scope) {
$scope.clkCount = 0;
var app = angular.module('ngClickApp', []);
app.controller('ngClickCtrl', function($scope) {
$scope.clkCount = 0;
});
<!DOCTYPE html>
<html lang="en-US">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<table>
<thead>
<tr ng-app="ngClickApp">
<th>
<button class="some-scss" ng-controller="ngClickCtrl" ng-click="clkCount=clkCount+1"><b>someCol {{clkCount}}</b></button>
</th>
</tr>
</thead>
</table>
</body>
</html>
Hi,
You should not put the script inside a table. Need to keep the script in a separate file or at the end of your HTML or just above the body tag inside HTML so that the page loads faster as javascript code can block/delay the loading process.
Try not to use scripts, CSS or HTML in the same file to keep the code easy to read, maintain and modify.
Thanks

How to change Background color of table row based on respective cell data using angularjs?

I want to change Background color of row based on cell data, like if it matches first four characters from table cell "td", then row should change its color to red.
here is my example, it is working but it takes whole cell data.but i want row color should change once it matches first four characters from cell.
<style>
.bgRed{
background-color:red;
}
</style>
<body ng-app="myApp">
<div ng-controller="myController">
<div class="container" style="margin-top:40px;">
<div class="row">
{{error}}
<div class="col-md-6">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Class Name</th>
<th>Roll No</th>
<th>Email</th>
</tr>
</thead>
<tbody ng-repeat="std in students">
**<tr ng-class="{'bgRed': std.Name === 'Prash'}>**
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
and my table is
Table row should change to red if table cell data "Prash or Prashant" matches.instead of taking "Prashant Olekar"
how to achive this please help. Thank you
Using substring you can trim the characters of the string,
here I'm creating one more variable(filed) "trimmed_name" which is a substring of your "name" which gives you first 4 characters of your string "name".
<tr ng-repeat="std in students" ng-init="trimName(std)">
<td ng-class="{'bgRed': std.trimmed_name === 'Prash', 'bgBlue': std.trimmed_name === 'Pavi', 'bgBlack' : std.trimmed_name === 'Pava'}">{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
In Css add respective colours for respective classes
in your controller
$scope.trimName = function (std) {
std.trimmed_name = std.Name.substring(0, 4);
return std;
};
Just in case if 'Prash' dose not work use {'bgRed': std.trimmed_name === "Prash"}
Hope it helps you.
you can use a custom filter to set class according to condition of your row data,
html
<tbody ng-repeat="std in students | filter:filterColor">
<tr class="{{std.class}}">
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
js
$scope.filterColor = function (item) {
if (your condition) {
item.class = 'your class';
}
else
item.class = 'some other class';
return true;
};
I have got solution to my question with the help of Rajat, here is my code. but it only matches characters from 0th Position.
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/App/app.js"></script>
<style>
.bgRed {
background-color: #cfeaff;
}
</style>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<div class="container" style="margin-top:40px;">
<div class="row">
{{error}}
<div class="col-md-6">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Class Name</th>
<th>Roll No</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="std in students" ng-init="trimName(std)" ng-class="{bgRed: std.trimmed_name === 'Pras'}">
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
and In Controller
/// <reference path="../angular.min.js" />
var myApp = angular.module('myApp', [])
.controller("myController", function ($scope, $http, $log) {
var successCallback = function (response) {
$scope.students = response.data;
$log.info(response);
}
var errorCallback = function (response) {
$scope.error = response.data;
$log.info(response);
}
$scope.StudentsData = $http({
method: 'GET',
url: 'PKWebService.asmx/getPkData'
})
.then(successCallback, errorCallback);
$scope.trimName = function (std) {
std.trimmed_name = std.Name.substring(0, 4);
return std;
};
});
and output is
Thank you

How can I change the innerHTML of div with a variable, inside the scope function in angular js?

I have 2 HTML pages. In my index.html page you can see products information that comes from JSON file. I need to have detail of product in detail.html page when people click on particular product. Alert can show the details but unfortunately the innerHTML of my <p> does not change, please guide me.
<div ng-app="myApp" ng-controller="AppController">
<div id="serachWrapper">
<h1 id="headerTopic">Our Products</h1>
<input id="searchInput" name="search" type="text" placeholder="Search products" ng-model="searchquery"/>
<table id="searchTable">
<thead id="tbHead">
<tr class="tbRow">
<th class="tbTopics">ID</th>
<th class="tbTopics">Name</th>
<th class="tbTopics">Color</th>
<th class="tbTopics">Type</th>
<th class="tbTopics">Capacity</th>
<th class="tbTopics">Price</th>
</tr>
</thead>
<tbody id="tbBody">
<tr class="tbRow" ng-repeat="x in myData | filter:searchquery ">
<td class="tbcontents" >{{x.id}}</td>
<td class="tbcontents">{{x.name}}</td>
<td class="tbcontents">{{x.color}}</td>
<td class="tbcontents">{{x.type}}</td>
<td class="tbcontents">{{x.capacity}}</td>
<td class="tbcontents">{{x.price}}</td>
</tr>
</tbody>
</table>
</div>
And this is my Angular js code:
var app = angular.module('myApp', ['ngSanitize']);
app.controller('AppController', AppController);
function AppController($scope , $http) {
$http.get("products.json").success(function(myData){
$scope.myData = myData;
$scope.go = function(item){
var detail = item.detail;
var productDetail = angular.element(document.getElementById('product-detail')).html();
productDetail = detail;
alert(detail)
};
});
}
You can keep both codes in the page and to solve this with an ng-if directive
Angular ng-if directive
<body ng-app="ngAnimate">
<label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/>
Show when checked:
<span ng-if="checked" class="animate-if">
This is removed when the checkbox is unchecked.
</span>
</body>
Why is your $scope.go function defined inside the http.get request?
Try:
function AppController($scope , $http) {
$http.get("products.json").success(function(myData){
$scope.myData = myData;
});
$scope.go = function(item) {
var detail = item.detail;
var productDetail = angular.element(document.getElementById('product-detail')).html();
productDetail = detail;
alert(detail)
};
}

AngularJs Sort orderBy not working properly in ng-repeat

Sorting not working properly on my inputField. After clicking on the inputField column, values got sorted, but problem is sorting not correct for modified values, all values are going bottom. I'm adding model-change-blur to sort after the blur in to text box. I don't know where I'm doing wrong. After modified values.
Here is my HTML Code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/bootstrap.min.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/myscript.js"></script>
</head>
<body ng-app="app" ng-controller="myController">
<table class="table table-bordered">
<thead>
<tr>
<th class="text-center" style="width: 65px;">
<div href="#" ng-click="sortType = 'id'; sortReverse = !sortReverse">
ID <span class="glyphicon sort-icon" ng-show="sortType=='id'" ng-class="{'glyphicon-chevron-up':sortReverse,'glyphicon-chevron-down':!sortReverse}"></span>
</div>
</th>
<th class="text-center" style="width: 65px;">
<div href="#" ng-click="sortType = 'checkBoxField'; sortReverse = !sortReverse">
Checked <span class="glyphicon sort-icon" ng-show="sortType=='checkBoxField'" ng-class="{'glyphicon-chevron-up':sortReverse,'glyphicon-chevron-down':!sortReverse}"></span>
</div>
</th>
<th class="text-center" style="width: 61px;">
<div href="#" ng-click="sortType = 'inputField'; sortReverse = !sortReverse">
Input <span class="glyphicon sort-icon" ng-show="sortType=='inputField'" ng-class="{'glyphicon-chevron-up':sortReverse,'glyphicon-chevron-down':!sortReverse}"></span>
</div>
</th>
</thead>
<tbody>
<tr ng-repeat="row in filtered = ( tableData | orderBy:sortType:sortReverse )" id="row-{{$index}}">
<td align="center" style="width: 68px;">{{row.id}}</td>
<td align="center" style="width: 68px;"><input id="checkBoxField-{{$index}}" type="checkbox" ng-model="row.checkBoxField" ng-true-value="'Y'" ng-false-value="'N'"/></td>
<td align="center" style="width: 61px;"><input id="inputField-{{$index}}" class="onlyNumber" type="text" ng-model="row.inputField" maxlength="3"style="width: 50px;" model-change-blur></td>
</tr>
</tbody>
</table>
</body>
And here is my Js file:
angular.module('app', [])
.controller('myController', function($scope) {
$scope.sortType = '';
$scope.sortReverse = false;
$scope.tableData = [];
for(i=1; i<= 8; i++){
$scope.tableData.push({"id":i,"checkBoxField": i%3==0 ,"inputField":1+i});
}
})
.directive('modelChangeBlur', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elm, attr, ngModelCtrl) {
if (attr.type === 'radio' || attr.type === 'checkbox') return;
elm.unbind('input').unbind('keydown').unbind('change');
elm.bind('blur', function() {
scope.$apply(function() {
ngModelCtrl.$setViewValue(elm.val());
});
});
}
};
});
Update: Adding Images
Without sorting table looks like below:
After sorting table ascending order looks like below:
After modified 3rd row order looks like below here is issue:
Modified value going to bottom row.
your sort code is fine.. just change the input type to number..
<input id="inputField-{{$index}}" class="onlyNumber" type="number" ng-model="row.inputField" maxlength="3" style="width: 50px;" model-change-blur> </td>
you just have an empty default sort column, just change this to define a default value. you can check by clicking one of the table head column and it'll sort properly.
$scope.sortType = 'inputField';
or you can add ng-init to your table tag like.
ng-init = "sortType='inputField'"
I'd also suggest to define an order function for a cleaner markup.
// code source https://docs.angularjs.org/api/ng/filter/orderBy
$scope.sort = function(sortType) {
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;
$scope.sortType = sortType;
};
and simply in your Markup, instead of
ng-click="sortType = 'inputField'; sortReverse = !sortReverse"
this
ng-click="sort('inputField')"
and initial code to either
ng-init = "sort('inputField')"
or
sort('inputField')
plunk
Check this one also
https://docs.angularjs.org/api/ng/filter/orderBy
I just make one function which is call when you leave from textbox.
$scope.changeData = function(predicate)
{
$scope.sortType = 'inputField'
$scope.sortReverse = true;
}
and here check how ng-blur call
<tbody>
<tr ng-repeat="row in filtered = ( tableData | orderBy:sortType:sortReverse )" id="row-{{$index}}">
<td align="center" style="width: 68px;">{{row.id}}</td>
<td align="center" style="width: 68px;">
<input id="checkBoxField-{{$index}}" type="checkbox" ng-model="row.checkBoxField" ng-true-value="'Y'" ng-false-value="'N'"/>
</td>
<td align="center" style="width: 61px;">
<input id="inputField-{{$index}}" ng-blur="changeData(sortReverse)" class="onlyNumber" type="text" ng-model="row.inputField" maxlength="3"style="width: 50px;" model-change-blur>
</td>
</tr>
</tbody>
//change syntax of ng-repeat as follows
<tr ng-repeat="row in filtered = ( tableData | orderBy:'-id' )" id="row-{{$index}}">
// add - for reverse sorting
<tr ng-repeat="row in filtered = ( tableData | orderBy:'-inputField' )" id="row-{{$index}}">

add row to first of the table angularjs

how i can row in angular to the first
html :
<title>Add Rows</title>
<link href="http://cdn.foundation5.zurb.com/foundation.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
</head>
<body ng-controller="MainController">
Add Row {{counter}}
<table>
<thead>
<tr>
<th width="200">Some Header</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rowContent in rows">
<td>{{rowContent}}</td>
</tr>
</tbody>
</table>
</body>
</html>
js :
angular.module('MyApp', [])
.controller('MainController', [ '$scope', function($scope) {
$scope.rows = ['Row 1', 'Row 2'];
$scope.counter = 3;
$scope.addRow = function() {
$scope.rows.push('Row ' + $scope.counter);
$scope.counter++;
}
}]);
http://codepen.io/calendee/pen/buCHf
in the example below
it added the row in the last , how i can it to be the first row not the last.
mate, just use unshift instead of push, then it will insert to the top of array,
$scope.rows.unshift('Row ' + $scope.counter);
$scope.counter++;
have done a fiddle for you:
http://codepen.io/anon/pen/QjPxvN?editors=101

Categories