Angularjs directive attribute can't wait for loading data - angularjs

I have a directive for showing a 'share to social networks menu'. It works fine in normal page but when i use it on a lightbox (that fetchs it's data after clicking on an item), it fails to pass attributes to share menu directive without any error. The variables are empty.
<item-actions data-itemid="{{popup.id}}"></item-actions>
Directive:
var itemActions_tmpl =
'<div>' +
// share button
'<div class="share-w">' +
'<button type="button" class="button radius share" value="share" >' +
'</button>' +
'<ul>' +
'<li><a target="_blank" data-ng-href="{{::fblink}}">Facebook</a></li>' +
'<li><a target="_blank" data-ng-href="{{::gplink}}">Google +</a></li>' +
'<li><a target="_blank" data-ng-href="{{::twlink}}">Twitter</a></li>' +
'</ul>' +
'</div>' +
'</div>';
jApp.directive('itemActions', ['APP_CONFIG', function(APP_CONFIG){
return {
replace:true,
scope: {},
restrict: 'AE',
template: itemActions_tmpl,
link: function(scope, Elem, Attrs, controller) {
scope.fblink = 'https://www.facebook.com/sharer/sharer.php?u=' + APP_CONFIG.BASE_ITEM_URL + Attrs.itemid;
scope.gplink = 'https://plus.google.com/share?url=' + APP_CONFIG.BASE_ITEM_URL + Attrs.itemid;
scope.twlink = 'http://twitter.com/home?status=' + APP_CONFIG.BASE_ITEM_URL + Attrs.itemid;
}
};
}]);
How can i fix this?

I used $q and problem solved. Just waiting for data and then opening popup.

Related

AngularJS directive and validation

I'm new here :)
Ok I have problem, I wrote the script like this:
var app = angular.module('myApp', []);
app.directive('formInput', function() {
return {
restrict: 'E',
require: ['^form'],
link: function(scope, element, attrs, ctr)
{
var form = ctr[0];
var newEl = '<div class="control-group">' +
'<div class="controls">' +
'<input type="text" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" required>' +
'</div>' +
'</div>' +
'<span ng-show="' + form.$name + '.' + attrs.formId + '.$error.required" class="help-block">Can\'t be blank</span>';
element.replaceWith(newEl);
}
}
});
and this html:
<div ng-app="myApp">
<form name="test321" novalidate>
<form-input required form-id="iddd" label="test"></form-input>
</form>
</div>
Im trying to get dynamic input but validation dosen't working, any one can help me please?
live link: http://jsfiddle.net/x9yuua94/

How to call directive template on click?

I am trying to make a reusable modal dialog and I would like to load directive template on click directive itself..
function modalDialog() {
var directive = {
restrict: 'A',
link: linkFunc,
template: '<div class="modalBox--blur">' +
'<div class="modalBox">' +
'<h3>' {{title}} '</h3>' +
'<h4>' {{text}} '</h4>' +
'<button ng-click="answer(true)">Cancel</button>' +
'<button ng-click="answer(false)">Ok</button>' +
'</div>' +
'</div>',
scope: {
title: '=dialogTitle',
text: '=dialogTxt'
},
transclude: true
};
return directive;
function linkFunc($scope, element, attrs) {
element.on('click', function () {
$scope.newEl = element.parent();
$scope.newEl.append(...template Here...???);
});
}
}
This is how directive is set in the view:
<button
modal-dialog
dialog-title="modalBox.title"
dialog-txt="modalBox.subText"
type="button"
ng-click="deleteSth()"
class="button">
</button>
I can't figure out how to load template on element click :
element.on('click', function () {
$scope.newEl = element.parent();
$scope.newEl.append(template????);
});
Any tips?
Thank you in advance!
You can get the template with $templateCache
Like $templateCache.get('templateId.html')
Solution was compiling the template:
scope.modal = $compile(' <div class="modalBox--blur">' +
'<div class="modalBox">' +
'<h3>{{title}}</h3>' +
'<h4>{{text}}</h4>' +
'<button ng-click="dialogAnswer(true)">Annuleren</button>' +
'<button ng-click="dialogAnswer(false)">Ok</button>' +
'</div>' +
'</div>')(scope);
element.on('click', function () {
scope.newEl = element.parent();
scope.newEl.append(scope.modal);

ng-model two way binding not working with ui bootstrap modal

I have following code for working with ui bootstrap modal. I am having a input field whose value has to be captured on the controller. But the input field value is not getting reflected on the controller after an value is entered on the modal.
angular.module('myApp')
.controller('mainController', ['$scope', '$modal', function($scope, $modal) {
$scope.openModal = function() {
$modal.open({
templateUrl: 'modal.html',
controller: BoardController
});
};
}])
.directive('modalDialog', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
template:
'<div class="modal-content">' +
'<div class="modal-header">' +
'<h4 ng-bind="dialogTitle"></h4>' +
'</div>' +
'<div class="modal-body" ng-transclude></div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" ' +
'ng-click="cancel()">Close</button>' +
'<button type="button" class="btn btn-primary" ' +
'ng-click="ok()">Save</button>' +
'</div>' +
'</div>'
};
});
var BoardController = function ($scope, $modalInstance) {
$scope.dialogTitle = 'Create new item';
$scope.placeholder = 'Enter item name';
$scope.inputname = '';
$scope.ok = function () {
console.log($scope.inputname);
$modalInstance.dismiss('cancel');
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
In 'modal.html' i have the following code:
<modal-dialog>
<input type="text" class="form-control" id="enter-name"
ng-model="inputname" placeholder={{placeholder}}>
{{ inputname }}
</modal-dialog>
So, after entering some text into the inputfield when i click the save the following line under $scope.ok() prints blank.
console.log($scope.inputname);
I guess this has something to do with scopes or may be transclusion. But i am not able to figure out whats causing this. I couldnt find the updated value in developer console also.
The problem here is transclusion. ngTransclude directive creates one more scope, but it is a sibling scope. Using transclusion makes it very difficult to access your scope. In your case you could retrieve model value like this:
$scope.ok = function () {
console.log($scope.$$childHead.$$nextSibling.inputname);
$modalInstance.dismiss('cancel');
};
But of course this is terrible. Fortunately, you can control what scope transclusion will use for rendered template if you make transclusion manually. For this you need to use link function with the fifth argument which is transclude function.
Your directive will become (note, that you don't use ng-tranclude directive in template anymore):
.directive('modalDialog', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
template:
'<div class="modal-content">' +
'<div class="modal-header">' +
'<h4 ng-bind="dialogTitle"></h4>' +
'</div>' +
'<div class="modal-body"></div>' +
'<div class="modal-footer">' +
'<button type="button" class="btn btn-default" ng-click="cancel()">Close</button>' +
'<button type="button" class="btn btn-primary" ng-click="ok()">Save</button>' +
'</div>' +
'</div>',
link: function(scope, element, attrs, controller, transclude) {
transclude(scope, function(clone) {
var modalBody = element[0].querySelector('.modal-body');
angular.element(modalBody).append(clone);
});
}
};
});
Demo: http://plnkr.co/edit/I7baOyjx4pKUJHNkxkDh?p=preview

Internet Explorer modal directive in angular js

Hello I had written following directive in angular js to use modal:
appname.directive("modal", function () {
return {
template: '<div class="modal fade" 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-hidden="true">×</button>' +
'<h4 class="modal-title">{{ title }}</h4>' +
'</div>' +
'<div class="modal-body" ng-transclude=""></div>' +
'</div>' +
'</div>' +
'</div>',
restrict: 'EA',
transclude: true,
replace:true,
scope:true,
link: function postLink(scope, element, attrs) {
scope.title = attrs.title;
scope.$watch(attrs.visible, function(value){
if(value == true)
$(element).modal('show');
else
$(element).modal('hide');
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
}
};
});
Its work fine in Chrome, IE 9 and firefox now I want it to work it in IE 8 , some blog says used document.createElement('directivenmae'), but its just create simple html element not include content of this template.
It would be nice if anyone provide suggestion for my this issue.
Ok, so first of all you will have to read the entire section on IE8 integration on Angular's website. There is a number of things that you have to do in order to make it work. Start there.
"They" are right that you have to call this piece of code:
document.createElement(yourTagName)
It's not intended to render anything, it is aimed to let IE8 know that you will be having some custom HTML tags in your markup.
Finally, please note that IE8 is not supported in AngularJS 1.3.+, so be advised and use latest 1.2.x branch.
After all that you will be good to go - I'm also using Bootstrap + Angular in IE8 and it works fine :)

Angularjs : Loop all isolated scope Directive Templates, on click of one

I have html:
<div ng-repeat="mydata in data" class="ng-scope ng-binding">
<p class="ng-binding">{{mydata.postdata}}</p>
<div my-rating rating-value="rating" data-cat="post" data-id="mydata.id" ></div>
<div ng-repeat="childData in mydata.personRelatedData">
{{childData.personName}}
<div my-rating rating-value="rating" data-cat="person" data-id="childData .id" >
</div>
</div>
I have a Directive :
myDirectives.directive('myRating', function () {
return {
restrict: 'A',
template: '<div><ul>' +
'<li ng-repeat="i in getNumber(myNumber)" ng-click="toggle($index)" id=$index>' +
'<div ng-switch="switchPoint<$index">'+
'<div ng-switch-when=true><img ng-src="img/{{Unrated}}"></div>'+
'<div ng-switch-when=false><img ng-src="img/{{Rated}}"></div>'+
' </div>' +
'</li></ul></div>',
scope: {
ratingValue: '=',
dataCat: '=',
dataId: '=',
readonly: '#',
onRatingSelected: '&'
},
link: function (scope, elem, attrs) {
scope.toggle= function(val) {
scope.ratingValue = val + 1;
scope.onRatingSelected({rating: null});
scope.switchPoint = val;
}
}
}
Currently i have implemented that on page load, the rating from the db comes, and while rendering the template, if rating for that ID exists, then it is rated on the isolated rating template too.
Now what I want is that on click of a rating, the execution should rate that ID celebrity, but also loop the other isolated templates, to see if ratings for that ID exist.. and if so, we can update their rating too.
How can I loop the other isolated templates on click of one?
Don't store the rating value in the scope of the directive, store the rating in a location that is accessible to all of the items.
mydata is a perfect location for this. Instead of passing the mydata.rating property directly to the directive (and thus passing a value), pass the whole mydata object, and reference the mydata.rating property within the directive. Since you're passing an object to the directive, it will be a reference, not a value, i.e. all of the directives which are passed the same mydata object will be looking at the same object, not copies of a particular property. You could achieve the same goal by making the rating property an object as well instead of a value.
EDIT: in response to comments, you could change it to be more direct.
myDirectives.directive('myRating', function () {
return {
restrict: 'A',
template: '<div><ul>' +
'<li ng-click="setRating(1)">' +
' <img ng-src="img/{{ myData.rating >= 1 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(2)">' +
' <img ng-src="img/{{ myData.rating >= 2 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(3)">' +
' <img ng-src="img/{{ myData.rating >= 3 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(4)">' +
' <img ng-src="img/{{ myData.rating >= 4 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(5)">' +
' <img ng-src="img/{{ myData.rating >= 5 ? Unrated : Rated}}">' +
'</li>' +
'</ul></div>',
scope: {
myData: '=',
readonly: '#',
onRatingSelected: '&'
},
link: function (scope, elem, attrs) {
scope.setRating = function(val) {
scope.myData.rating = val;
scope.onRatingSelected(scope.myData);
}
}
}
I don't expect this example to work with just copy/paste to your problem; it's just meant as an idea to get your rolling.

Resources