how to hide smart table after deleting all rows? - angularjs

I am displaying smart table using ng-show and sg-hide ..condition is data is null then hiding table and data existed showing table. It is working every time page fresh load, but I want to apply if emptied the table by deleting rows. angularjs and smarttable are resources
At first load it is following ng-hide and ng-show to display table or other div. If no data to display then I am hiding, else data existed I am showing when I emptied all rows by delete row action then after all rows deleted... then ng-hide is not working I am using angularjs and smarttable
HTML
<div `enter code here`ng-hide="hasdata"->
<smarttable></smarttable>
</div>
<div `enter code here`ng-show="hasdata">
NO data to disply
</div>
Controller
$scope.columncollection;$scope.rowcollection and using http to get data and fill rowcollection object. and we r deleting row by using custom directive. At first load if data length is zero it works fine but row deleted then its not hiding.

Your table is not getting hidden because, you probably have not changed the value of hasdata to false after you delete the table contents.
Try this,
In html,
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script data-require="angular.js#1.0.7" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="smart-table.js"></script>
<script src="script.js"></script>
<link href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css" rel="stylesheet">
</head>
<body ng-controller="mainCtrl">
<h1>{{greetings}} Plunker!</h1>
<div ng-show="hasdata">
<smart-table config="globalConfig" columns="columnsConfig" rows="items"></smart-table>
</div>
</body>
</html>
In Js file,
var app=angular.module('myApp',['smartTable.table']);
app.controller('mainCtrl',['$scope',function(scope){
scope.greetings='hello';
scope.hasdata=true;
scope.doDelete = function(index) {
// alert("index "+index);
scope.items.splice(index,1);
if(scope.items.length===0){
//alert("scope.items.length "+scope.items.length);
scope.hasdata=false;
}
}
scope.items=[
{name:'mahesh',lastName:'kumar'},
{name:'sachin',lastName:'ramesh'},
{name:'varun',lastName:'gupta'},
{name:'vijay',lastName:'kumar'},
{name:'prem',lastName:'raj'},
{name:'gandhi',lastName:'gandhi'},
{name:'sathish',lastName:'kumar'},
{name:'ram',lastName:'prasad'},
{name:'siva',lastName:'guru'},
{name:'dilli',lastName:'ganesh'}
];
scope.globalConfig={
isPaginationEnabled:false,
selectionMode:'single'
};
scope.columnsConfig=[
{label:'name',map:'name'},
{label:'last Name',map:'lastName'},
{label:'actions',cellTemplateUrl:'delete.html'}
];
}])
In delete.html,
<button ng-click="$parent.$parent.$parent.$parent.doDelete(displayedCollection.indexOf(dataRow))"
class="btn btn-xs btn-primary">
Delete
</button>
Have a look at the working demo in plunker
Hope this solves your problem :)

If you are sure that the hide condition is true (data is null) after deleting all the table rows, something you can check by logging (console.log) the condition after each row delete, then you probably just need to perform a $scope.apply() or $scope.digest() to ensure your view is updated.
If you add your code to the question then it will be easier to give you a more complete answer.

You probably have to wrap the code deleting rows in an $apply call.
$scope.$apply(function() {
//delete rows here
})

Related

Include template on ng-click in angulajs

I have created discussion forum application in angularjs. Once the user clicked the reply button on the post, I want to show the editor which is in the separate html file. How can I include that template on clicking the ng-click under that specific post.
How about a combination of ng-include with ng-if?
If you want to inject a template based on a certain condition, you can do it like this:
<div ng-include="'template.html'" ng-if="yourCondition"> </div>
where template.html is your filename and yourCondition should be an boolean expression.
Here is a plnkr to demonstrate: http://plnkr.co/edit/m50nKigoOWYwuczBIQdQ?p=preview
As suggested above we can use combination of ng-if and ng-include to achieve require functionality :
<html ng-app="includeApp">
<head>
<script type ="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<script src="AppController.js"></script>
</head>
<body ng-controller="AppCtrl">
<button ng-click="injectReply()">Include Reply</button>
<div ng-include="'reply.html'" ng-if="isReplyIncluded"></div>
</body>
</html>
Now code containing AppController.js :
angular.module('includeApp',[])
.controller('AppCtrl',['$scope',function($scope){
$scope.isReplyIncluded=false;
$scope.injectReply= function (){
//add reply.html by making this variable true
$scope.isReplyIncluded=true;
}
}]);
Reply.html
<div>
You can add your editor html content here
</div>

AngularJS Databinding Expression not working inside tooltip plugin template

*EDIT: Mike pointed out an issue with a type. the real problem i want to solve includes a template with cluetip. See this revised plnkr:
http://plnkr.co/edit/UGH3cV3z9MrqA4eyPjLc?p=preview
I'm sure this is related to the digest loop and the jquery plugin cluetip, but I don't know what steps I need to make the data binding work inside template. I've put the simple example in plnkr to show what I mean.
http://plnkr.co/edit/YW7AsTEuJh2ixqSUJpld?p=preview
The code in question is this:
head>
Cluetip - AngularJS
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<link rel="stylesheet" href="jquery.cluetip.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="jquery.cluetip.js"></script>
<script type="application/javascript">
$(function() {
$('a.title').cluetip({
splitTitle: '|'
});
});
</script>
</head>
<body ng-app>
<input ng-model="somedata" placeholder="Some Data">
<br/>{{ somedata }}
<hr/>
<br/>
<a class="title" href="#" title="This is the title| someData: {{ someData }} .|In this case, the delimiter is a pipe">In Line Text</a>
</body>
Couple of issues going on here...
First, you don't have a controller managing this, so the scope that is created by the tag is not visible to the somedata reference in your tooltip title. To correct this, you need to reference a controller:
<body ng-controller="MainCtrl">
and setup the somedata scope value in that controller:
$scope.somedata = 'somedata';
Second, you have a small typo in the title reference (you have a capital "D" in somedata):
title="This is the title| someData: {{ someData }} .|In this case, the delimiter is a pipe"
should be
title="This is the title| someData: {{ somedata }} .|In this case, the delimiter is a pipe"
And, finally, it appears the jQuery cluetip code is creating a copy of the value, so it's not dynamic. In reality, it's probably setting up the DOM objects once at initialization and never referencing the "title" attribute again -- just hiding and showing the created content. Therefore, changing the value of the "title" attribute appears to be ignored.
I forked a Plnkr here with the above changes (including referencing the script.js file where a controller now resides): http://plnkr.co/edit/hzW6AtJBj4zPPM405n5Y?p=preview
Notice it all works; however, the cluetip doesn't change dynamically as the somedata value changes. I made a duplicate of the anchor below the first one in the Plnkr, but changed the class so cluetip wouldn't attach and it's a standard tooltip. You'll see that this tooltip does update dynamically -- using the same input box and somedata.
Beyond the above, I think you'll have to find a way to either trigger and update to the cluetip initialization or use a different widget. As an aside to all this, you'd probably be better served exploring a native angular directive for this so you don't run into this type of issue. Maybe something like http://angular-ui.github.io/bootstrap/#/tooltip

Get selected buttons of btn-group (buttons-checkbox) with angularjs

I'm using bootstrap and angular to build an application. In a HTML page, i'm using this:
<div class="btn-group-justified" data-toggle="buttons-checkbox">
<button type="button" class="btn fzbtn-consServices" ng-repeat="service in availability.services">{{service.name}}</button>
</div>
It's building a button group with dynamic values. Is there a practical way to obtain the selected buttons inside this button group?
I already tried some solutions, some of them are working but I don't know if it's the best way...
1: On "ng-click" method I would change a attribute value (eg. "checked" attribute) of each service to true or false;
2: I searched about any html attribute for btn-group which could offer me all the selected buttons inside this group, but i had no success;
3: I heard that i could beat this problem using Angular Filter, but i didn't find any similar example;
Anyone with a better idea? Thanks so much :)
This is the best solution I found until now:
<div class="btn-group-justified" data-toggle="buttons-checkbox">
<button type="button" class="btn fzbtn-consServices" ng-repeat="service in availability.services" ng-click="onClickService(service)" ng->{{service.name}}</button>
</div>
Controller:
$scope.onClickService = function (service) {
if (service.checked) {
service.checked = "false"
} else {
service.checked = "true";
}
}
Answer: Bootstrap UI
I feel your pain. Bootstrap is not always angular-friendly. But there is a good solution:
The easiest (and by far the cleanest) approach is to use Bootstrap UI. Built by the Angular Team, it is a rewrite of the javascript-portion of Bootstrap but for an Angular-friendly usage. Here's the section about buttons: http://angular-ui.github.io/bootstrap/#/buttons
Example solution: Checkbox button behavior
In this solution, the initial services array is used to store a boolean field 'selected' to know if any particular service is selected or not. (Similar to the "checked" in the question). This field is 2-way bounded to the checkbox state. Clicking the checkbox changes the field and changing the field changes the checkbox state.
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
var services = [
{ name:'Service A' },
{ name:'Service B', selected:true },
{ name:'Service C' },
{ name:'Service D', selected:true }
];
$scope.availability = { services:services };
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS BootStrap UI radios</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"></script>
<script src="app.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-controller="MainCtrl">
<div class="btn-group-justified">
<label ng-repeat="service in availability.services" class="btn btn-primary" ng-model="service.selected" btn-checkbox>{{service.name}}</label>
</div>
<div ng-repeat="service in availability.services">{{service.name}} <span ng-show="service.selected">- selected</span></div>
</body>
</html>
Radio button behavior
I've included a solution for a "single selection" checkbox also known as a "radio-button". The "current selection" is bound to a variable on the scope. It will get updated automatically when the user picks an element. Setting it will, in turn, change the current selection.
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
var services = [
{ name:'Service A' },
{ name:'Service B' },
{ name:'Service C' },
{ name:'Service D' }
];
$scope.availability = { services:services };
$scope.model = {};
// Here we are using the service object instance as the "selection value".
// Depending on what you need, you could also use some sort of identifier or
// even the $index if that's more useful.
// Immediately select the second one.
$scope.model.selectedService = services[1];
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS BootStrap UI radios</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js"></script>
<script src="app.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-controller="MainCtrl">
<div class="btn-group-justified">
<label ng-repeat="service in availability.services" class="btn btn-primary" ng-model="model.selectedService" btn-radio="service">{{service.name}}</label>
</div>
<div>Current Selection is: {{model.selectedService.name}}</div>
</body>
</html>
NOTE: I used <label> instead of <button>, but I did not have your special CSS styles so it wasn't behaving on the screen, functionality-wise it works equally well with <button> elements.
You don't really specify why you are wanting to "get" the buttons. In general, getting a reference to DOM elements like this is not the "angular way." It is generally better to find a way to use angular's data-binding to manipulate UI elements.
For instance, if you want to show or hide buttons based on data or on another UI event, then use ng-show or ng-hide bound to a property of the service object you are binding these buttons to. Then you can update the object's property to change the UI. You should be able to find a similar way to make other changes (like setting classes, attributes, etc.) with angular's data-binding rather than doing it manually.

AngularJS searching by nested data

I am new to AngularJS. I am trying to get a simple search based on the users name, which in my case is not stored on the top most layer. Here is the example:
<div ng-init="users = [
{'fields':{'name':'Mary Brown','person_nickname':'M'},'username':'mbrown'},
{'fields':{'name':'John Smith','person_nickname':'J-Dog'},'username':'jsmith'}]">
</div>
Here is the plnkr that searches all the fields I want to take this and make it such that it only searches fields.name. In this plunker, I could type "dog" and still get the second user returned, which is not what I want.
I tried changing my input ng-model to search.fields.name but when I do that, the search doesn't activate at all. I can type in any string into the text box and nothing is filtered out.
What am I missing? Thank you!
EDIT:
Full code since plunker is currently down:
<!doctype html>
<html ng-app="App">
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<div ng-init="users = [
{'fields':{'name':'Mary Brown','person_nickname':'M'},'username':'mbrown'},
{'fields':{'name':'John Smith','person_nickname':'J-Dog'},'username':'jsmith'}]">
</div>
Name only <input ng-model="search.fields"><br>
<table id="userTable">
<tr ng-repeat="user in users | filter:search">
<td>{{user}}</td>
</tr>
</table>
</body>
</html>
Plnkr is not running right now, but if you have an ng-repeat which you want to filter, then look at the official docs, especially upvoted comments are useful: http://docs.angularjs.org/api/ng.filter:filter
item in myArray | filter:{propertyThatWillBeFiltered: value}
If you are talking about searching inside your model, then you should use "filter" method on an array.

ReCaptcha & Underscore.js Templates

I am running into an issue in my backbone/underscore application. Our site uses recaptcha and we want to put that content inside a view. We are using underscore for templates. How would i put the recaptcha code inside a template? THe problem is there are scripts tags required for recaptcha and it collides with the underscore script tag. For example it would look something like this:
<script type="text/javascript" id="someTemplate">
<div>
some html here
</div>
<script type="text/javascript" src="https://www.google.com/recaptcha/api/challengek=YOUR_PUBLIC_KEY"
 
</script>
any help is appreciated. Thanks!
Underscore does not prevent you from using script tags, your problems come from your template declaration : you use type="text/javascript" which means your browser tries to interpret your template as Javascript and you get erratic results.
Try
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<script type="text/javascript"
src="https://www.google.com/recaptcha/api/challengek=<%= key %>"
/>
</script>
and a demo http://jsfiddle.net/VxjBs/
As you noted in the comments, Recaptcha tries to loads a second script via document.write and fails when inserted in the DOM (see Can't append <script> element for a probable explanation).
Your best bet is probably to go through Recaptcha Ajax API, generate your HTML, identify a node and apply Recaptcha.create on it. Something like
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<div class='recaptcha'></div>
</script>
The basis for a view could be
var html = _.template(src, {
text: 'in div'
});
var $el = $('#render').append(html);
$el.find('.recaptcha').each(function(idx, el) {
Recaptcha.create(
pubkey,
el
);
});
http://jsfiddle.net/nikoshr/VxjBs/2/
Not sure what all the reCAPTCHA script does, but I'm assume it tries to append HTML right after itself. If that's the case then you will probably need to manually attach a script node to the view after you've rendered it and then set the src of the script node to the URL of the external javascript file.
You cannot put script tags inside an underscore template as the browser will only parse the outer-most script tag (your template).
The proposed solution is too complicated.
This can be achieved very easily as follows (in fact I've just implemented it in my project).
Make sure to include the recaptcha js file in the "head" element of your page as follows:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Add this function in your javascript somewhere.
var render_recaptcha = function(target_id) {
grecaptcha.render(target_id, {
'sitekey' : RECAPTCHA_SITE_KEY
});
};
Then, just call this function after you render your template:
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<div id='recaptcha'></div>
</script>
//render template like you usually would
//...
//then render the recaptcha
render_recaptcha('recaptcha');
That's it.

Resources