Angular-Strap Alerts: Unable to capture when alert.hide() triggers - angularjs

I am trying to implement an automatic alert into my AngularJS application using Angular-Strap and the $alert service. So far so good, however, I am left with an issue I can't seem to resolve.
Is there a way I can I set a callback to capture when the $alert is hidden either using the duration property or the alert.hide() command? I want to run a function when the alert goes into a hidden state.
My code snippets looks like this:
var alertContent = '';
// Define the critical alert
var criticalAlert = $alert({
templateUrl: 'templates/critical.alert.tpl.html',
title: ' Critical Alert Detected!',
content: alertContent,
container: 'body',
type: 'danger',
dismissable: false,
duration: '20',
show: false
});
...
alertContent = 'Foo Bar!';
...
criticalAlert.$promise.then(criticalAlert.hide);
...
$scope.$on('alert.hide', function() {
console.log('Alert Hidden');
});

The result of the $promise, you can pass your own function, eg:
criticalAlert.$promise.then(function(){criticalAlert.hide();console.log('Alert Hidden'); })
More about $promise anglular $q
UPDATE
You can use $watch.
Of course, it's not a nice solution, but the best I found. At least, it works!
var alert = $alert({
title: ' Critical Alert Detected!',
content: 'its Alert!',
container: 'body',
type: 'danger',
dismissable: false,
duration: '5',
show: false,
});
$scope.$watch(function(){return alert.$isShown;},function(val){
if(val===true)
console.log('alert opened',val);
else
console.log('alert closed',val);
});
alert.$promise.then(alert.show);
UPDATED 2
We can use event of angular.
Live example on jsfiddle.
.controller('ExampleController', function($scope, $alert) {
$scope.alert = $alert({
title: ' Critical Alert Detected!',
content: 'its Alert!',
container: '#divForAlert',
type: 'danger',
dismissable: false,
duration: '5',
show: false,
prefixEvent:"mymodal",
});
$scope.alert.$promise.then(function() {
$scope.alert.show();
});
$scope.$root.$on('mymodal.hide.before', function(event) {
console.log('hide before',event);
});
$scope.$root.$on('mymodal.hide', function(alert) {
console.log('hide',alert);
});});
And some important html
<div ng-controller="ExampleController">
<h3>
ExampleController
</h3>
<form name="ExampleForm" id="ExampleForm">
<div id="divForAlert">
</div>
</form>

Related

Polymer 1.0: How can I add paper-card heading content dynamically

Is there a way I can create paper-card heading dynamically using some property inside custom element? Following is what I tried but didn't work. Probably this is not the way to achieve what I want:( I googled for a couple of hours but ended up with nothing!
Custom Element
<script>
(function () {
'use strict';
Polymer({
is: 'nearest-customers',
properties: {
customers: {
type: Array,
value: [],
notify: true
},
cardViewMaxRecords: {
type: Number,
notify: true
},
showFullCustomerList: {
type: Boolean,
value: false,
notify: true
},
headingContent: {
type: String,
value: 'Custom card heading'
}
},
ready: function () {
this.heading.textContent = this.headingContent
},
});
})();
</script>
HTML
<nearest-customers id="nearestCustomers" card-view-max-records="3"></nearest-customers>
...
...
...
<script type="text/javascript">
window.addEventListener('WebComponentsReady', function (e) {
var nearestCustomers = document.querySelector("#nearestCustomers");
nearestCustomers.headingContent= "<a href='someurl'><iron-icon icon='fa:arrow-left'></iron-icon></a> This is a new content";
}
</script>
My objective is to put an iron-icon before the heading text and the icon can be used as a link to somewhere.
Thanks in advance
I'm sure there's a better way, but I just added the styles and structure:
<div class="header paper-card">
<div class="title-text paper-card">
<iron-icon icon="book"></iron-icon> Reading List
</div>
</div>

Angular Bootstrap Accordion issue

I am trying to create accordion to loop my data.it is partially working, but I need to dynamically add new part into accordion. at beginning I need to open the first one, but after user save it and click add,I need to open the second one, and close others. My code is:
<accordion close-others="oneAtATime">
<accordion-group
heading="{{destination.length}}"
is-open="status.isFirstOpen"
is-disabled="status.isFirstDisabled"
ng-repeat="destination in mileage.destionations">
<select ng-model='destination.Type'
id='type'
ng-options='Type for Type in mileageTypes'
ng-init='mileageTypes[0]'
ng-change='updateReimbur(destination)'>
</select>
<select ng-model='destination.Reimbursable'
id='reimbursable'
disabled="true"
ng-options='reimbursable for reimbursable in mileageReimbursment'
ng-init='mileageReimbursment[0]'>
</select>
</accordion-group>
</accordion>
JS:
$scope.mileage.destionations = [{
Type: '',
Reimbursable: "Yes",
Distance: true,
Odometer: false,
Total: 0,
From: '',
To: ''
}];
$scope.addNewDestionation = function () {
$scope.NewDestionation = {
type: '',
reimbursable: "Yes",
Distance: true,
Odometer: false,
total: 0,
From: '',
To: ''
}
$scope.mileage.destionations.push($scope.NewDestionation);
}
$scope.status = {
isFirstOpen: true,
isFirstDisabled: false
};
How can I always leave the last one(New one) open and close the others?
I'm sure you will get that working, by following these hints :
Replace close-others="oneAtATime" with close-others="true".
On all the repeated elements, you are writing : is-open="status.isFirstOpen", which is equivalent to is-open="true". This is your main mistake, as you're saying all groups should be opened.
Try to maintain a reference to the opened group. You could maintain an array of statuses but something like that will also do the trick, and avoid you to maintain all statuses :
is-open="status[$index].isOpen"
is-disabled="status[$index].isDisabled"
$index is an angular variable that references the index of the repeated element in the array. I leave you the js logic for the maintenance of the status object.
For the sake of style, correct the typo in destionations (destinations), initialize your default new destination in a variable outside the function addNewDestionation, and push that variable. Like that :
var newDestination = {
type: '',
reimbursable: 'Yes',
Distance: true,
Odometer: false,
total: 0,
From: '',
To: ''
};
$scope.addNewDestionation = function () {
$scope.mileage.destionations.push(newDestination);
}
close-others attribute takes a boolean value. You should either define
$scope.oneAtATime = true
or
<accordion close-others = "true">
If I've undestood it correctly you could do it like this.
Add a property openState to your destination object and change it like you need it. So keeping the second active could be done be setting every state to false except the second one.
It's similar to 2. form Michael's answer and I also think creating a status variable to keep track of the open states is probably better here.
Please have a look at the demo below (it's a reduced version of your code to keep things easier to read) or here at jsfiddle.
angular.module('demoApp', ['ui.bootstrap'])
.controller('mainController', MainController);
function MainController($scope) {
var itemCount = 0; // just to have an increasing title
$scope.oneAtATime = true;
$scope.mileage = {};
$scope.mileage.destionations = [{
Type: '',
Reimbursable: "Yes",
Distance: true,
Odometer: false,
total: itemCount,
From: '',
To: '',
openState: true
}];
$scope.addNewDestination = function () {
var index = $scope.mileage.destionations.length,
openState = (index == 1);
angular.forEach($scope.mileage.destionations, function(destination, index) {
// turn all off except second
destination.openState = (index == 1);
});
itemCount++;
var newDestination = {
type: '',
reimbursable: "Yes",
Distance: true,
Odometer: false,
total: itemCount,
From: '',
To: '',
openState: openState
};
$scope.mileage.destionations.push(newDestination);
}
$scope.status = {
isFirstOpen: true,
isFirstDisabled: false
};
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.2/ui-bootstrap.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.2/ui-bootstrap-tpls.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
<accordion close-others="oneAtATime">
<accordion-group is-open="destination.openState" heading="{{destination.total}}" ng-repeat="destination in mileage.destionations">
{{destination|json}}
</accordion-group>
</accordion>
<button ng-click="addNewDestination()">add</button>
</div>

How to do validation in $ionicPopup?

I'm trying to use $ionicPopup to handle login/registration on my app.
I'm opening it from a service, so I created a new scope and attached it to the ionicPopup.
It looks something like this:
$ionicPopup.show
template: '''
<form name="loginForm" novalidate>
...
</form>
''',
scope: $scope,
buttons: [
{
text: 'Cancel',
},
{
text: '<b>Save</b>',
type: 'button-positive',
onTap: ( e ) ->
form = $scope.loginForm #why is it undefined?
}
]
So I named the form as loginForm, and I want to access it inside the onTap function to handle validation. But the loginForm does not exists on the $scope, like it would in a normal form validation inside a controller.
How should I handle the validation here?
If you give ionicpopup a templateUrl, instead of hard coded template string, you can use a regular controller inside the template that does the validation.
I deleted all the ionicpopup related buttons and placed the necessary buttons inside the template.
In this way I was able to control the ionicpopup's state from the controller (i.e. closing the popup).
I found solution, it works for me. All you need to change is define in controller your form:
$scope.form = {
loginForm: {}
};
$ionicPopup.show
template: '''
<form name="form.loginForm" novalidate>
...
</form>
''',
scope: $scope,
buttons: [
{
text: 'Cancel',
},
{
text: '<b>Save</b>',
type: 'button-positive',
onTap: ( e ) ->
form = $scope.form.loginForm
}
]
Using my solution, you don't have to delete the ionic popup buttons.
What you can do to validate, is by using ng-Model.
You don't have to use <form>. So I remove <form>.
$ionicPopup.show
template: '<input name="username" ng-model="data.username">',
scope: $scope,
buttons: [
{
text: 'Cancel',
},
{
text: '<b>Save</b>',
type: 'button-positive',
onTap: ( e )
var user_name = $scope.data.username
// do validation here
if(user_name != 'undefined') {
...
}
}
]
I prefer not to remove the ionic popup buttons. Hope it is useful to others. cheers!
Use
onTap: ( e )
e.eventPreventDefault()
var user_name = $scope.data.username
// do validation here
if(user_name != 'undefined') {
...
}

AngularJS Modal Dialog with File Upload Control not working

I am using AngularJS Modal Service. http://fundoo-solutions.github.io/angularjs-modal-service/
I setup it in a simple way
Button to open a Model
<div data-ng-controller="contest as vm">
<a class="btn btn-primary" data-ng-click="vm.createFileUploadDialog()">Upload Image</a>
</div>
Inisde Controller I have a function defined createFileUploadDialog and expose it from my viewModel.
vm.createFileUploadDialog = createFileUploadDialog;
vm.uploadme = {};
vm.uploadme.src = "";
function createFileUploadDialog() {
createDialog('/app/templates/fileuploadDialog.html', {
id: 'filuploadDialog',
title: 'Upload Contest Image',
backdrop: true,
success: { label: 'Upload', fn: uploadSuccess },
cancel: { label: 'Cancel' },
});
}
function uploadSuccess() {
console.log(vm.uploadme);
//need to call to the backend
}
And inside "fileUploadDialog.html" I have a simple markup
<div>
<input type="file" fileread="uploadme.src" />
</div>
"fileread" is a directive which return back the src of the File. Now the problem I have
As you can see I am doing console.log inside "UploadSuccess", in response I am getting the result "Object {src: ""}",
It looks like the Modal values not capture inside controller. But If I do the same with $rootScope, it logs out the File that need to upload. So, how can I access the value without using $rootScope? Please suggest
PS:
I am not define separate controller for Modal, want to use the same controller that treats my view.
** Modals scope is not the same as your controller scope!**
if you want to see your Controller scope inside of your modal and manupulate it , you're gonna have to use resolve inside of your modal markap like this :
createDialog('/app/templates/fileuploadDialog.html', {
id: 'filuploadDialog',
title: 'Upload Contest Image',
backdrop: true,
success: { label: 'Upload', fn: uploadSuccess },
cancel: { label: 'Cancel' },
resolve:{
controllerscope:function(){
return $scope;
}
}
});
And now , inside of your modal controller you can inject :** controllerscope ** and use it , also data binding works well like this :
app.controller('modalcontroller',function($scope,controllerscope){
// no you have access to your controller scope with **controllerscope**
})
So go and have a look at your modal plug in wich you are using and search for resolve and controller
thats it

Unit test ng-grid with Qunit

I'm writing unit test for ng-grid by using Qunit frameword. Here is my implementation:
module("Test grid angular", {
setup: function(){
injectorGrid = angular.injector(["ng", "ngGrid"]);
$scope = injectorGrid.get('$rootScope').$new();
$scope.currentPortfolioList = [
{
'symbol': 'bbb',
'available': 100,
'mortage' : 0
},
{
'symbol': 'AAA',
'available': 0,
'mortage' : 1000
}];
$scope.gridTest = {
data: 'currentPortfolioList',
enableCellSelection: false,
enableCellEditOnFocus: true,
multiSelect: false,
columnDefs: [
{field: 'symbol', displayName: 'Ma'},
{field: 'available', displayName: 'KL GD'},
{field: 'mortage', displayName: 'KL CC'}
]
};
},
teardown: function(){
$("#gridview").html("");
}
});
test('hide column', function(){
$scope.gridTest.columnDefs[0].visible = false;
var el = '<div ng-grid="gridTest"></div>';
var $compile = injectorGrid.get('$compile');
var element = $compile(el)($scope);
$("#gridview").html(element);
$scope.$digest();
var col0 = element.find(".col0");
ok(col0.length == 0);
});
Although my test case is passed, I see an error message on console log of the Firefox browser as follow:
[$compile:ctreq] http://errors.angularjs.org/1.2.16/$compile/ctreq?p0=ngInclude&p1=ngInclude
\<\div class="ngHeaderScroller" ng-style="headerScrollerStyle()" ng-include="gridId' 'headerRowTemplate.html'"
I found that this error happens when calling: $compile(el)($scope);
Can you help me resole this issue?
Use Batarang to look at the nginclude directive in question:
gridId' 'headerRowTemplate.html'
is not a valid reference.
This error occurs when HTML compiler tries to process a directive that specifies the require option in a directive definition, but the required directive controller is not present on the current DOM element (or its ancestor element, if ^ was specified).
To resolve this error ensure that there is no typo in the required controller name and that the required directive controller is present on the current element.
References
Error: $compile:ctreq
Missing Required Controller

Resources