I'm using angularJs. I would like to include a variable into a popover template.
angular.forEach($scope.myList, function (obj) {
obj.details = '<div uib-popover-html="' + template/template.html + '" type="button"' +
'popover-placement="bottom" name="' + obj.id+'" id="' + obj.id+'" ' +
'popover-trigger="\'click\'"> ' +
'<i class="glyphicon glyphicon-eur"></i></div>';
The template is quite simple:
<div>
<button ng-click="onClick(object.id)"></button>
</div>
What is my problem is I don't know how to link this object.id with the forEach. So, for me it is just a template with a param.
Is it possible to do?
Related
I'm using Angular Treeview to build a hierarchy in my website. I've added a Bootstrap Dropdown to each node in the hierarchy, it is displayed when the user clicks on the node label.
The menu items displayed in the dropdown is different depending on the type of the node. All this I've gotten to work.
Now when the user wants to add a node a bootstrap modal is supposed to open for user input. This is where I'm stuck, the modal does not get called at all. I've gotten functions within the directive working using $(".dropdown > ul.dropdown-menu").html($compile(appendThis)(scope));, but if I want to open a model defined in the directive template it does not work.
I've tried the solutions here and here, but they are not working.
Here is a simplified version of the directive template:
template =
'<div class="modal hide fade" id="addThisNode"">'+
'<div class="modal-body">'+
'<p>This Node Body</p>'+
'</div>'+
'</div>'+
'<div class="modal hide fade" id="addOtherNode"">'+
'<div class="modal-body">'+
'<p>Other Node Body</p>'+
'</div>'+
'</div>'+
'<ul>' +
'<li data-ng-repeat="node in ' + treeModel + '">' +
'<i class="normal" '+
'data-ng-hide="node.' + nodeChildren + '.length">'+
'</i> ' +
// Call this funcion when
// the node label is clicked
'<span class="treenode {{node.' + nodeType + '}}" '+
'id="{{node.' + nodeId + '}}"'+
'data-ng-class="node.selected" '+
'data-ng-click="' + treeId +
'.selectNodeLabel(node)">'+
'{{node.' + nodeLabel + '}}'+
'</span>' +
// bootstap dropdown menu
'<div class="dropdown" data-ng-show="node.selected">'+
'<a data-toggle="dropdown"><span class="caret"></span></a>'+
'<ul class="dropdown-menu">'+
// list items get appended here
'</ul>'+
'</div>'+
'</li>' +
'</ul>';
If the user clicks the node label this function is called:
scope[treeId].selectNodeLabel = scope[treeId].selectNodeLabel || function( selectedNode ) {
// set currentNode
scope[treeId].currentNode = selectedNode;
// Get the node type
var nodetype = scope[treeId].currentNode.NodeType;
var appendThis = '';
if (nodetype == 'This'){
appendThis = '<li><a data-target="#addThisNode" href="" data-toggle="modal">Add This Node</a></li>';
}
else if (nodetype == 'Other'){
appendThis = '<li><a data-target="#addOtherNode" href="" data-toggle="modal">Add Other Node</a></li>';
}
$(".dropdown > ul.dropdown-menu").html($compile(appendThis)(scope));
};
Sorry if this is confusing, it's confusing to me as well. But if you have tips on calling modals from inside a directive anything will be appreciated.
After searching through a lot of posts I was able to find an answer. I'm posting it here in case it can help anyone else.
I changed the structure of the template a bit, but the functionality stays the same. The actual problem was in compiling the template. It worked when I compiled it like this:
$(".dropdown > ul.dropdown-menu").html(appendThis);
$compile($(".dropdown > ul.dropdown-menu").contents())(scope);
I've created a new template/datepicker/popup.html template that get's loaded after ui.bootstrap.tpls.
What I'm struggling with is calling a function from ng-click in the new template. I don't want to update the ui.bootstrap.tpls file. I've attempted this two different ways:
1) Less Ideal: Use the select function already within directive datepickerPopup from ui.bootstrap.tpls. I can get this to work partially by converting to .toLocaleDateString() but after the first click I open the calendar again and the calendar still shows current date instead of reflecting the updated date.
"<button class='btn btn-default' ng-click='select(date.setTime(date.getTime()+30 * 86400000).toLocaleDateString())'>30 days</button>" +
2) Ideal: Create a brand new function outside of ui.bootstrap.tpls called addDays(n). I can't reach this function from the new template. I would like to create my own function to call from the new template.
"<button class='btn btn-default' ng-click='addDays(date, 30)'>30 days</button>" +
Plunker:
http://plnkr.co/edit/Klbek5SpOGIA4FXTmlFX?p=preview
I spent more time tinkering with this today and came up with a solution to my own questions.
When you override the template add ng-controller="ControllerName" to the outer element in my case a div. Then you need to add your controller to the module, in my solution I just added the controller right into the popupTemplate.js.
Updated Plunker:
http://plnkr.co/edit/YLJW2imcDAbzwsvp58Rl
Javascript FileName popupTemplate.js. Code:
(function() {
'use strict';
angular.module("template/datepicker/popup.html", [])
.run(["$templateCache", function($templateCache) {
$templateCache.put("template/datepicker/popup.html",
"<div ng-controller='ExampleCtrl'>" +
"<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\" ng-keydown=\"keydown($event)\">\n" +
" <li ng-transclude></li>\n" +
" <li ng-if=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
" <span class=\"btn-group pull-left\">\n" +
" <button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"select('today')\">{{ getText('current') }}</button>\n" +
" <button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"select(null)\">{{ getText('clear') }}</button>\n" +
" </span>\n" +
" <button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"close()\">{{ getText('close') }}</button>\n" +
" </li>\n" +
"</ul>\n" +
"<div class=\"dropdown-menu-extend\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px'}\">" +
"<h4 >or select a future date here...</h4>" +
"<div class='col-lg-6'>" +
"<h5>Add a new function</h5>" +
"<button class='btn btn-default' ng-click='select(addDays(date, 30))'>30 days</button>" +
"</div>" +
"</div>" +
"</div>" +
"");
}])
.controller('ExampleCtrl', function ($scope) {
$scope.addDays = addDays;
function addDays(date, days) {
var newDate = date.setTime(date.getTime()+days * 86400000); //epoch date
var finalDate = new Date(newDate); //formatdate
console.log(finalDate);
return finalDate;
}
});
})();
I have and AngularJS 1.0.7 web application and I´m using AngularStrap select directive. Everything was working fine until I have moved my application to html5Mode. I did that to prettify my URLs.
But now, when I select an option in any bs-select component I´m redirected to index.
HTML
<select class="show-tick" ng-model="selectType" ng-options="boatType as (boatType.name | translate) for boatType in boatTypes" bs-select>
<option value="" selected>{{'BOAT_TYPE' | translate}}</option>
</select>
JS Controller:
$scope.$watch('selectType', function() {
if($scope.selectType != undefined) {
BoatModel.query({type_id: $scope.selectType.id},
function success(result){
if(result.length == 0){
$scope.boatModels = new Array ();
$scope.selectModel = undefined;
SearcherService.setModel(undefined);
}
else{
$scope.boatModels = result.slice();
}
}
);
SearcherService.setType($scope.selectType.id);
$scope.selectModel = undefined;
}
else {
SearcherService.setType(undefined);
$scope.selectModel = undefined;
}
});
I fixed it.
I found out the code generated by the Bootstrap Select directive is not compatible with html5Mode because it inserted an href="#" in each option in the select. When you click on it you are redirected to the index.
Original Code in the directive
createA:function(test, classes) {
return '<a tabindex="-1" href="#" class="'+classes+'">' +
'<span class="pull-left">' + test + '</span>' +
'<i class="icon-ok check-mark"></i>' +
'</a>';
I just fixed it by removing the href, like this:
createA:function(test, classes) {
return '<a tabindex="-1" class="'+classes+'">' +
'<span class="pull-left">' + test + '</span>' +
'<i class="icon-ok check-mark"></i>' +
'</a>';
I am new to AngularJS and trying to build an AngularJS practice app, in which, the user will concatenate a url from multiple inputs, i.e. protocol, domain, path, param1, param2, param3... etc.
And the app will create a link to the url:
<a>{{protocol}}://{{domain}}{{path}}?{{param1}}&{{param2}}&{{param3}}</a>
Above url is used twice. Once on the href attribute, as well as the actual text. Now what I want to do is something like:
{{url}}
But I am not sure where to assign url.
I tried below, and it worked, but doesn't seem correct.
<a href='{{url = protocol+"://"+domain+path+"?"+param1+"&"+param2+"&"+param3}}'>{{url}}</a>
Assuming that url is used many times in the app, where would be the most appropriate place to assign url?
You shouldn't assign scope variables in the view (the HTML) - it's only for reading them.
To make a new variable from inputs, add a ng-model to each of them and then in the controller define a method that makes a $scope variable from them e.g.
Your HTML form:
<div ng-controller="MyCtrl">
<input type="text" ng-model="urlParts.protocol">
<input type="text" ng-model="urlParts.domain">
<!-- etc -->
<a ng-href="{{makeUrl()}}">{{makeUrl()}}</a>
</div>
JS:
function MyCtrl($scope) {
$scope.urlParts = {};
$scope.urlParts.protocol = "";
$scope.urlParts.domain = "";
// etc...
// These values will be updated when the user types in the input boxes
$scope.makeUrl = function() {
return $scope.urlParts.protocol + "://" + $scope.urlParts.domain + $scope.urlParts.path + "?" + $scope.urlParts.param1 + "&" + $scope.urlParts.param2 + "&" + $scope.urlParts.param3;
}
}
Another similar approach is to use ng-init directive to create a dynamic property which represents the concatenation of all those properties. You can call the function or just concatenate inline.
<a ng-init="urlParts.url=makeUrl()"
ng-href="urlParts.url">{{urlParts.url}}
</a>
<a ng-init="urlParts.url=urlParts.protocol + '://' + $scope.urlParts.domain..."
ng-href="urlParts.url">{{urlParts.url}}
</a>
Reference:
http://www.ozkary.com/2015/03/angularjs-ng-model-concatenate-model.html
Try It: http://plnkr.co/edit/PSvwCE?p=info
If you want to bind a dynamic url with href then you can manipulate you URL in ng-click or ng-mousedown event and bind to target element.
JS:
var goToLinkedPage = function (event, basePath, param1, param2, param 3) {
var newState = basePath + "?" + param1 + "&" + param2 + "&" + param3;
jQuery(event.target).attr('href',newState);
};
HTML:
<a ng-mousedown="goToLinkedPage($event, basePath, param1, param2, param3)"> Click Here </a>
Just use this binding expression to concatenation of more than two scope variables in HTML.
{{UserData.FirstName + ' ' + UserData.MiddleName + ' ' + UserData.LastName}}
If you want to do this inside any attribute, Just write like this:
<input type="text" ng-value="UserData.FirstName + ' ' + UserData.MiddleName + ' ' + UserData.LastName">
I am new to Snecha so please bear my non technical description.
MyView.js
itemTpl: [
'<div class="pb10 font-90">{associationDiplayText}</div>' +
'<div style="float:left">' +
'<div class="bold font-90"><b>{name}</b></div>' +
'<div class="font-90">{address1}</div>' +
'<div class="font-90">{address2}</div>' +
'</div>' +
'<div style="display:block;" class="fltR" id="displayIcon">' +
'<span id="phoneId" class="phoneIcon"></span>' +
'<span id="emailId" class="emailIcon"></span>' +
'<div class="clr"></div>' +
'</div>' +
'<div class="clr"></div>' +
'<div style="display:none" id="display" class="mt15 mb10">'+
'<tpl for="contacts">',
'<div style="float:left">' +
'<div class="font-50">{contactTypeText}:</div>' +
'<div class="font-50">{name}</div>' +
'</div>' +
'<div class="fltR" id="innerdisplay">' +
'<span id="contactphone" class="phoneIcon"></span>' +
'<span id="contactemail" class="emailIcon"></span>' +
'<input type="hidden" value="{#}" id="hiddenindex" />'+
'<div class="clr"></div>' +
'</div>'+
'<div class="clr"></div>' +
'</tpl>',
'</div>'+
'<div align="center">{moreDetail}</div>'
]
Controller.js In onItemTap I am doing following
onItemTapListView: function(view, itemIndex, target, record, event, eOptions) {
if(event.getTarget("#contactphone.phoneIcon")){
var contactRecord = record.data.contacts[itemIndex];
}
The problem is that when i click the first row it gives itemIndex = 0 which is what I expect but it also gives the same result when I click on phoneIcon from contact list which has around 10,15 items. what I need is to get the index on which contact item user has clicked.
Thanks in Anticipation
Each instance of the 1st-level record object will be set to a different row no mather what it contains.
ST wont ever know on which contact is the user tapping because the entire row is a single unit.
I know the UI would be different, but my recommendation is to go with a Nested List approach.
regards-