Bootstrap and angular - pass object to modal - angularjs

I create table using bootstrap and angular use object to display data. I want to open popup window to change object property by clicking row (and use angular binding in modal to work with object).
So my issue that i doesn't understand how to pass object from table to modal.
I found many examples with passing values and changing html on fly but in my case i want to use angular for binding and want to pass reference to object.
Sample of table:
<table class="table table-condensed table-bordered">
<thead>...</thead>
<tbody>
<tr ng-repeat="property in properties" data-toggle="modal" data-id="property" data-target="#editPropertyModal">
<td>{{property.name}}<td/>
<td>{{property.value}}<td/>
<td>...<td/>
</tr>
</tbody>
</table>
So by clicking this row i want to open modal and pass there property object and use controls like input, combobox to bind values via angular.
My sample of modal:
<div class="modal fade" id="editPropertyModal" tabindex="-1" role="dialog" aria-labelledby="editPropertyModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="editPropertyModalLabel">Property details</h4>
</div>
<div class="modal-body">
{{currentProperty.name}} - {{currentProperty.value}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
My try to pass property via javascript:
$(document).on("click", ".open-editPropertyModal", function (e) {
e.preventDefault();
var _self = $(this);
var property = _self.data('id');
$("#currentProperty").val(property);
$(_self.attr('href')).modal('show');
});
Doesn't work.

You can use this to do that. It really helped me.

Default Bootstrap JavaScript is not working well with angular, because it makes changes in DOM model outside AngularJS. Please consider using native directives for bootstrap, like these http://mgcrea.github.io/angular-strap/
Also, for maximum simplicity, in many cases, you can use something like this plugin https://github.com/cgross/angular-prompt. It depends on bootstrap and gives you simple API based on promises.
prompt({
title: 'Give me a name',
message: 'What would you like to name it?',
input: true,
label: 'Name',
value: 'Current name',
}).then(function(name){
//name contains new value
});
Callback passed to then will be executed after clicking "OK" in popup.

Related

Custom AngularJS directive with xeditable: doesn't work first time, but works afterward

Building an AngularJS application, I'm using xeditable to allow the user to edit a table, row per row (as described here: xeditable).
The Edit, Remove and Cancel button logic being a bit cumbersome to implement in each table, I created a custom directive: sen-edit-row.
The logic of the buttons in the custom directive works well... except in one case.
When the user clicks [Add], a row is added (just like in xeditable's example), and the new row is immediately editable. Or it should!
The very first time, the row is not editable. The input fields are not created by xeditable. The buttons of my own directive still work.
But the most bizarre thing is: the 2nd time the user clicks [Add], it just works. And then it keeps working!
(this is driving me nuts)
In the HTML, the directive is called this way:
<tr ng-repeat="access in denyAccessTable">
<td class="col-md-4"><div editable-text="access.user" e-form="rowForm">{{ access.user }}</div></td>
<td class="col-md-4"><div editable-text="access.host" e-form="rowForm">{{ access.host }}</div></td>
<td class="col-md-2"><div editable-text="access.mode" e-form="rowForm">{{ access.mode }}</div></td>
<td class="col-md-2"><div sen-edit-row save="saveDenyAccess()" remove="removeDenyAccess($index)" shown="access == newDenyAccess"></div></td>
</tr>
In the JS, the directive is defined as:
angular.module("app", ["xeditable"]).directive("senEditRow", [function() {
return {
restrict: "A",
templateUrl: "sen-edit-row.html",
scope: {
save: "&",
remove: "&",
shown: "="
},
link: function(scope, element, attrs) {
}
}
}])
And the template of the directive:
<div style="white-space: nowrap">
<form class="form-inline" editable-form name="rowForm" onaftersave="save()" ng-show="rowForm.$visible" shown="shown">
<button type="submit" class="btn btn-primary" ng-disabled="rowForm.$waiting">Save</button>
<button type="button" class="btn btn-link" ng-disabled="rowForm.$waiting" ng-click="shown ? remove() : rowForm.$cancel()">Cancel</button>
</form>
<!-- Buttons to edit and remove -->
<div ng-hide="rowForm.$visible">
<span class="glyphicon glyphicon-edit" style="margin-right: 5px;"></span>Edit
<span class="glyphicon glyphicon-trash" style="margin-left: 10px; margin-right: 5px;"></span>Remove
<button class="btn btn-danger" ng-click="remove()" ng-show="showDeleteButton">Remove</button>
<button class="btn btn-link" ng-click="showDeleteButton = false" ng-show="showDeleteButton">Cancel</button>
</div>
</div>
I also created a Plunker that shows evidence of this behavior.
Question: How do I make my directive and xeditable work consistently, including the first time, and activate immediately when a row is added to the table?
Thank you!

angular-ui-router-uib-modal: reload page below when click outside the modal

I'm using angular-ui-router-uib-modal and I have a question on it.
When I close my modal (which confirm a successfull/failed operation), I need to reload page below (that show a list of data). As shown in the example below, I can specify that behavior in 'Close' button and also in 'X symbol' to close modal (with the ui-sref-opts="{reload: true}").
But... How can I specify the same operation when a user clicks outisde the modal and automatically closes the modal itself?
<div class="modal-content">
<div class="modal-header">
<div class="bb8-modal-close" ui-sref="home.gestioneFondi({gestione:true, innescatoDaMenuLaterale:false})" ui-sref-opts="{reload: true}">
<span class="visuallyhidden glyphicon glyphicon-remove-circle"/>
</div>
<h4 class="modal-title modal-title-font">Info</h4>
</div>
<div class="modal-body" ng-switch="esito">
<p class="text-center modal-body-font" ng-switch-when="true">Success</p>
<p class="text-center modal-body-font" ng-switch-when="false">Error</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ui-sref="home.gestioneFondi({gestione:true, innescatoDaMenuLaterale:false})" ui-sref-opts="{reload: true}">Chiudi</button>
</div>
</div>
Thank you for any help
So when you open a modal like this it is returning the promise:
var modalInstance = $modal.open({..});
you can specify the modal closing event on the promise
modalInstance.result.then(function (result) {..});
You can specify below code to reload the state.
$state.reload();
For above to work, you have to inject $state dependency in your controller.
app.controller('controller', ['$state',function($state){..}])

Protractor Locating elements by by.repeater contained within a specific div

In protractor, I am trying to access the buttons repeated withina specific div with id 'CreateRFQID'. These buttons are defined a directive 'gps-button-bar'. I am trying to access them by.repeater. Because these buttons also appear else where in the page, I can not just access them through
element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index')).
But I am trying without success to get those buttons that are sub element of the div with id 'CreateRFQID'.
Protractor code I am trying:
var parent = element(by.css('#CreateRFQID'));
var first= parent.element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index')).row(0);
first.getText().then(function (text) {
console.log(text);
});
Any help how to get it?
Thanks.
View / html Fragment
<div ng-controller="CreateRFQController as createRFQCntrl" id="CreateRFQID" class="ng-scope">
<gps-button-bar config="createRFQCntrl.buttonBarConfig" class="ng-isolate-scope"><div class="container-fluid">
<div class="row row-buttonBar">
<label><h1 class="panel-title ng-binding">RFQ Create </h1></label>
<span class="pull-right">
<span ng-repeat="aBtn in buttonBarController.config.buttonConfigs track by $index" style="padding-right: 2px" class="ng-scope">
<button class="btn btn-default btn-xs ng-binding" id=""myButton"+$index" ng-click="buttonBarController.clickHandler($index);" data-toggle="tooltip" data-placement="top" title="Create" ng-show="buttonBarController.gpsShownButtons[$index]" ng-disabled="buttonBarController.gpsDisabledButtons[$index]">
<span class="fa fa-floppy-o"></span> Create
</button>
</span><!-- end ngRepeat: aBtn in buttonBarController.config.buttonConfigs track by $index -->
</span>
</div>
You have a problem in the selector, you don't do .row on the result of element but on the by
var parent = element(by.id('CreateRFQID'));
var first = parent.element(by.repeater('aBtn in buttonBarController.config.buttonConfigs track by $index').row(0));
first.getText().then(function (text) {
console.log(text);
});

angular bootstrap html popover not being displayed

I'm trying to use the uib-popover-html directive and it doesn't display. If I use the uib-popover or uib-popover-template directive it displays correctly. Am I missing something?
This works
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'app/login/popover.html',
title: 'Title'
};
<!-- popover.html -->
<div>
<b style="color: red">I can</b> have <div class="label label-success">HTML</div> content
</div>
<!-- /popover.html -->
<button uib-popover="I appeared on mouse enter!" popover-trigger="mouseenter" type="button" class="btn btn-default">Mouseenter</button>
<button uib-popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" type="button" class="btn btn-default">Popover With Template</button>
This doesn't
<button uib-popover-html="htmlPopover" class="btn btn-default">HTML Popover</button>
Try using $sce (Strict Contextual Escaping) to show that the HTML is safe:
$htmlPopover = $sce.trustAsHtml('<div>Popover Content</div>');
This feature exists to avoid user's from inputting HTML that could be nefarious into a form, etc.
References: https://docs.angularjs.org/api/ng/service/$sce

Follow download link and dismiss modal?

I have inherited a GUI written with Angular, and at the moment I don't even know enough to trim it down to a fiddle. So I'm hoping this is more straightforward than it appeared on a quick Google.
I have a modal dialog created using Bootstrap that is basically the same as the live demo here: http://getbootstrap.com/javascript/
A copy of the source from that link:
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
The main difference in my case is that the "Save Changes" button is actually a link - to a resource which is downloaded without leaving the page. It looks like this:
<a ng-href="{{downloadUrl}}" class="btn btn-primary">Download</a>
My goal is to have the above modal dialog dismissed when the link is clicked, while still downloading the file. If I use data-dismiss, the download doesn't happen.
If I need to go digging around the code, that's fine, but I'm hoping there's a simple change to the template that will do the trick. Any suggestions?
First, when using with AngularJS 1.x, always use Bootstrap UI.
When using Bootstrap UI's $uibModal, it is way easier to manipulate the modal, and pass data between the view and the modal. The reason the link does not work, is because the modal should be closed first.
You can create a simple function which replaces href or ng-href: It closes the modal first, and goes to the link second.
And, remember, please do not use jQuery, and always try to use AngularJS dependencies like $window instead of window, when they're available. This also goes for onclick. always use ng-click, and handle the logic in your controller.
In your template, add the controller, and an ng-click-attribute:
<div ng-controller="MyCtrl as $ctrl">
<a href target="_blank" class="btn btn-primary" ng-click="$ctrl.go('#/some/url')"> Go </a>
</div>
In your controller, add the logic, for closing the modal, and following the link:
app.controller('MyCtrl', function($uibModalStack, $window) {
this.go = function(path) {
$uibModalStack.dismissAll();
$window.location.href = path;
}
})
You have to close the modal yourself. Here is a bootstrap.js only solution without angular. In angular you would open the modal with angular-bootstrap and close it also that way.
<a ng-href="some-reosource-url" target="_blank" class="btn btn-primary" onClick="closeModal()">Download</a>
function closeModal() {
$('#myModal').modal('hide');
}
http://plnkr.co/edit/0sRb5VdT9isEFdJ66Rxe?p=preview
Here's a working Plunker.
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.hideAndDownload = function() {
$('#myModal').modal('hide');
var link = document.createElement("a");
link.download = "data:text/html";
link.href = "http://code.jquery.com/jquery-1.11.3.min.js";
link.click();
}
});
Markup
<button type="button" class="btn btn-primary" ng-click="hideAndDownload()">Save changes</button>

Resources