I have an app that has buttons in a table. The button that is clicked should theoretically Hide the table and change some data. When the button is outside of the table it works fine, but inside it fails. Here is my code.
HTML:
<body link="white" vlink="white">
<pin>Site ID</pin>
<center>
<h1>Site Finder</h1>
<button ng-click="'x=0','y=0'">test</button>
<div ng-controller="firstCtrl">
<input type="text" ng-model="search" border="3" placeholder="Please enter site name..." ng-hide="hideAttr"/>
<div link="white" vlink = "white"><button id="btn2" ng-click="hideAttr = !hideAttr" ng-hide="!hideAttr">Back To Search</button></div>
<table border="1" width="100%" ng-hide="hideAttr">
<thead>
<tr>
<td><center>Name</center></td>
<td>Carrier</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="site in SiteLocs | filter : search">
<td>
<button id="btn1" ng-click="hideAttr = !hideAttr">
{{site.name}}
</button>
</td>
<td>
{{site.carrier}}
</td>
</tr>
</tbody>
</table>
</div>
</center>
<div id="map-canvas" ng-show="!hideAttr"></div>
</body>
</html>
JS:
(function(){
$scope.hideAttr = true;
});
Why wont the button work in a table?
That button is contained within an ng-repeat directive. ng-repeat creates it's own child scopes, so what is actually happening is you're creating a new $scope variable on the child scope called hideAttr and setting it. A couple work arounds:
Define a function in your controller and call that - Angular will look up to the parent and find the method
Use $parent in your ng-click method: ng-click="$parent.hideAttr = !$parent.hideAttr"
As #tymeJV pointed out the ng-repeat creates new scopes. When you are changing a primitive value on the child scope it creates a copy that hides the parent attribute. In the controller you should have an object that has the primitive attribute you want to change i.e.
$scope.tableAttrs = { hide: false };
and inside the ng-repeat markup you would use:
<div ng-hide="tableAttrs.hide">something to hide</div>
<button ng-click="tableAttrs.hide = !tableAttrs.hide">hide</button>
heres a blog post explaining it (related to forms but same idea, the child scope hides the primitive value) http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/
Related
I am new to Angularjs and I am trying to figure out how it's different modules work. So, I am working on a project on which I wanna achieve an accordion-like style for a page, in which a table is shown when I click a panel button. The HTML code that creates(dynamically from a database) the div elements I modify is posted below.The problem is that in this panel, any number of tables can be shown,while I need to only have one opened at a time,so when one opens,the one opened before it should close.Any ideas how I can achieve this functionality?(I assume the error is because the showDB variable is local to each table scope, but I don't know how to work around it.) Thanks!' `
<div ng-repeat="(key, value) in data.services">
<div ng-show="showSection(key)" class="top_panel-section">
<button class="btn top_btn btn-header" type="button" name="showDB"
ng-click="showDB=!showDB">{{key}}</button>
<table ng-show="showDB"
class="n-table toptable table-responsive n-table-standard n-table-striped n-table-hover">
<thead class="n-table-thead">
<tr>
<th width="70%">VM Name</th>
<th width="30%">Status</th>
</tr>
</thead>
<tbody class="n-table-body">
<tr ng-repeat="vm in value.vms">
<td width="76%">{{vm.vm}}</td>
<td width="24%" ng-style="getStatusStyle(vm.status)">
{{vm.status}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
Yes, you should remove that local showDB variable to achieve what you need.
You can easily replace it with a $scope.activeKey and evaluating it by the
<button ... name="showDB" ng-click="activateKey(key)">{{key}}</button>
And in your controller:
$scope.activeKey = null;
$scope.activateKey = function (keyToBeActivated) {
$scope.activeKey = keyToBeActivated;
}
Now you can reach that exclusivity by checking:
<table ng-show="activeKey === key" ... >
Using table $index as unique field: (available from ng-repeat)
<button ... name="showDB" ng-click="activateKey($index)">{{key}}</button>
And
<table ng-show="activeKey === $index" ... >
I have an inventory page that also contains a password field.
I would like to hide the password when the page is loaded, best would be to have points displayed **** and after click password is shown or a pop up.
JS
var get_cert = function () {
$http.get($scope.url.cert_list).then(
function (response) {
$scope.certs = response.data;
}
);
}
// execute get function
get_cert();
HTML
<div class="panel panel-default">
<table class="table table-striped valign_middle">
<tr class="table_header">
<td>Name</td>
<td>Pass</td>
</tr>
<tr ng-repeat="cert in certs | filter:search | orderBy:['name']">
<td>{{cert.name}}</td>
<td>
<button class="w3-btn w3-black w3-hover-green w3-ripple" ng-click="get_cert()">Show</button>
<span ng-show="get_cert()">{{cert.password}}</span>
</td>
</tr>
</table>
<button ng-show="!cert.showPw" class="w3-btn w3-black w3-hover-green w3-ripple" ng-click="cert.showPw = true">Show</button>
<span ng-show="cert.showPw">{{cert.password}}</span>
You can use ng-click to do cert.showPw = true, which will append a property called showPw (a boolean) to the object. Combined with ng-show, you can easily switch between the two.
This way you'll keep your controller free of any additional logic needed. You may include ng-click on the span which holds the password which will set showPw = false to switch it back to a button.
See my JSFiddle for full example.
Create a input
<input type="password" name="???">
Then you can change its type to "text" with
$("#idOfInout")type = 'text';
Is there a way to read through an HTML page and return the value of the dynamic checkboxes which are clicked?
Now, I know how to get values from static check boxes even without using JS but since I am generating the below check boxes using data from Database I am not sure how to pin point each one and know which one the user checked,
When I went through developer tools in chrome I can see that the value of the generated check boxes changes but when I refer to them it still does not work.
<!DOCTYPE html>
<html lang="en">
<form action="/test" method="post">
<button type="submit" id="exporst-btn" class="btn btn-primary">Import Test Data <span class="glyphicon glyphicon-import"></span></button>
<br>
<br>
<div id="table">
<table class="table table-condensed">
<thead>
<tr>
<th>Selection</th>
<th>Slno</th>
<th>Region</th>
</tr>
</thead>
<tbody>
{% for obj in TD %}
<tr>
<td>
<input type="checkbox" name="chb[]" > {{obj.OEHR_Mtest_Slno}}
</td>
<td>
{{obj.OEHR_Mtest_Slno}}
</td>
<td>
{{obj.OEHR_Mtest_SF_Part_Number}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!--<p id="export" name="test"></p>-->
<input type="hidden" id="exp" name="test">
<button type="submit" id="export-btn" class="btn btn-success">Execute <span class="glyphicon glyphicon-play"></span></button>
</form>
</body>
<script type="text/javascript"><!--
$('#export-btn').click(function () {
alert($('#mytable').find('input[type="checkbox"]:checked').length + ' checked');
});
</script>
</html>
I can use the above JS to know how many checkboxes have been checked, I want to know the value of the ones checked and I am not able to get that.
If I'm not mistaken,
var foo = $('#mytable').find('input[type="checkbox"]:checked')
will return an array of html elements which are checkboxes, and are checked. You can then do:
var bar = [];
foo.each(function (index) {
var baz = this.parentNode.textContent || this.parentNode.innerText;
if (baz && baz.length > 0)
bar.push(baz);
});
console.log(bar);
That will make bar an array of the values which were checked. It gets the checkboxes which were checked, finds their parents (<td> tags), and gets the text inside (which skips the <input> tags). This will do it client-side.
Because you're dynamically generating the checkboxes, it's helpful to also dynamically generate the values for the checkboxes. That way, when you POST the request via the submit button, Flask can determine which checkboxes were checked by reading the values. I would change your HTML to:
{% for obj in TD %}
<tr>
<td>
{# Assuming obj.OEHR_Mtest_Slno is a unique value #}
<input type="checkbox" name="chkbox" value="{{obj.OEHR_Mtest_Slno}}"> {{obj.OEHR_Mtest_Slno}}
</td>
<td>
{{obj.OEHR_Mtest_Slno}}
</td>
<td>
{{obj.OEHR_Mtest_SF_Part_Number}}
</td>
</tr>
{% endfor %}
Then in your backend, you can access the values via:
# Use .getlist if you are using HTML form elements with the same name
chkbox_values = request.form.getlist('chkbox') # returns a list of values that were checked
How to get the nested repeater textbox control in client side event of parent Repeater control.
I have a checkbox in each repeater item of the parent repeater control and textbox in each repeater item of the child Repeater. On the checkbox change event I need to find if there is any value in the child repeater textbox of that item in the client side.
I gave a class to the textbox, but the below code loops through all the textboxes inside the parent repeater.
$('.RepeaterTextBox').each(function () {
var txtvalue= $(this).val();
Rendered HTML for a single parent looks like this
<table>
<tr>
<td>
<input id="chkActive_0" name="chkActive" />
</td>
</tr>
<tr>
<td>
<div id="divText" style="padding-left: 15px; display: none;">
<table style="width: 100%">
<tr>
<td>
<div id="Category_0">
<textarea name="txtCategoryText" rows="2" cols="20" id="CategoryText_0" class="RepeaterTextbox"></textarea>
</div>
</td>
<td>
<div id="Category_1">
<textarea name="txtCategoryText" rows="2" cols="20" id="CategoryText_1" class="RepeaterTextbox"></textarea>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
Try this, it seems there are multiple textarea you have in nested repeater so the second line in the event handler will loop through each textarea and print value in console.
$("[type=checkbox]").on("change", function () {
var oTexts = $(this).parents("tr").next().find("textarea");
$(oTexts).each(function (ind, val) { console.log($(val).val()); });
});
You can use the checklist parent() property
Assuming your rendered html look like this
<div id="repeater_435734957439857435">
<input type="text" class="RepeaterTextbox">Test</input>
<input type="checkbox">
</div>
Your checkbox select event can be something like
$(this).parent().find(".RepeaterTextbox")[0].text();
This should work with your markup:
$(document).ready(function () {
$(document).on("click", "input:checkbox[name='chkActive']:checked", function () {
var nexttr = $(this).closest('tr').next('tr');
$(nexttr).find('textarea').each(function () {
alert($(this).val());//Or whatever you want
})
});
});
I'm trying to build a template for a application and want to display a dynamic list with names. so i got this code to show the list and add/remove rows;
<table ng-init="page.businessRows = []">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Phone</th>
</tr>
</thead>
<tr ng-repeat="row in page.businessRows">
<td>
<input type="text" ng-model="row.name" />
</td>
<td>
<input type="text" ng-model="row.contact" />
</td>
<td>
<input type="text" ng-model="row.phone" />
</td>
<td>
<button ng-click="page.businessRows.splice($index,1)">
Remove
</button>
</td>
</tr>
</table>
<button class="btn" ng-click="page.businessRows.push({})">addRow</button>
the thing as that when this template is loaded page.busnessRows will most likely be loaded with rows so i want to change the ng-init to only create the empty array if businessRows is not initialised.
I have tried ng-init="page.businessRows = page.businessRows.length < 1 ? [] : page.businessRows but it did not work. How am i inteded to do conditions in jsangular expressions?
All help appreciated. Thanks in advance
You can do this instead:
<table ng-init="page.businessRows = page.businessRows || []">
Update
I look at the parser code of AngularJS and notice that version 1.2 (currently RC) supports ternary expression. So if you use AngularJS 1.2, this will also work (although more verbose than the above code):
<table ng-init="page.businessRows = page.businessRows == null ? [] : page.businessRows">
See demo here.
However, your original code might not work if page.businessRows is null, because the parser will fail to dereference length property of null. So just be careful there.
I don't think the ng-init will evaluate conditional statements properly. But you could refactor the condition into a controller function and call the function from ng-init.
<table ng-init="initializeBusinessRows(page.businessRows)">
The just put your conditional evaluation in the function on the controller scope.
I think you're trying to solve the wrong problem.
The problem is that you're allowing an action to occur before the data is loaded or ready. A secondary problem is you're using an expression in an ng-click where a scope function or controller function should be.
So...
Disable that button if the form isn't ready.
Use your controller to control these interactions.
So here's an example of the controller. The $timeout was added to simulate a delayed load of data into your $scope.page variable.
app.controller('MyCtrl', function($scope, $timeout, $window) {
//Timeout to simulate the asynchronous load
//of the page object on the $scope
$timeout(function(){
$scope.page = {
businessRows: []
};
}, 2000);
//scope method to add a row.
$scope.addRow = function (){
//for safety's sake, check to see if the businessRows array is there.
if($scope.page && angular.isArray($scope.page.businessRows)) {
$scope.page.businessRows.push({});
}
};
//scope method to remove a row
$scope.removeRow = function(index, row) {
if($window.confirm('Are you sure you want to delete this row?')) {
$scope.page.businessRows.splice(index, 1);
}
};
});
... and the HTML view (notice the ng-disabled and the ng-click) (and lack of ng-init):
<div ng-controller="MyCtrl">
<table>
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in page.businessRows">
<td>
<input type="text" ng-model="row.name" />
</td>
<td>
<input type="text" ng-model="row.contact" />
</td>
<td>
<input type="text" ng-model="row.phone" />
</td>
<td>
<button ng-click="removeRow($index, row)">
Remove
</button>
</td>
</tr>
</tbody>
</table>
<button class="btn" ng-disabled="!page" ng-click="addRow()">addRow</button>
</div>
Also, here's the obligatory Plunker for you to see this in action.