angularjs ng-click getting info from child element - angularjs

I am trying to get info from the ng-click element. When I log $event from clicked element I get the right info but when I click the child element of then I get the info about the child and not the parent where the ng-click is set. Here is the fiddle link
http://jsfiddle.net/g3x2ndyc/5/.
var app = angular.module('app',[])
app.controller('appCtr', function($scope) {
$scope.testThis = function(evt){
//evt.stopPropagation();
// evt.preventDefault();
console.log(evt.srcElement.offsetLeft)
console.log(evt.srcElement.offsetWidth)
console.log('____________________________')
}
});

use evt.currentTarget not evt.srcElement (that one is mainly for IE).
Look at fiddle http://jsfiddle.net/g3x2ndyc/11/
var app = angular.module('app',[])
app.controller('appCtr', function($scope) {
$scope.testThis = function(evt){
console.log(evt.currentTarget.offsetLeft)
console.log(evt.currentTarget.offsetWidth)
console.log('____________________________')
}
});

Hard to tell exactly what you are ultimately trying to do, but you can just pass the id in to the click event then grab the position based on that.
ng-click="myevent('idName')
myevent(id) {
jquery('#'+id).position();
}

Related

How to call a method in the child window in Angular JS

My angular JS application has a view button. When clicking on the view button, it will call method and that method changes the content in the same page. Now I have a request that when clicking on the view button, it has to open in a new tab and display the contents.
Previous code:
HTML:
<md-button ng-click="ctrl.ViewClick(item)">View</md-button>
Controller:
vm.ViewClick = function(item) {
// The browser URL is same but it is a new page with the new contents.
// Calls a angular js service and loads the contents
}
Now, I need to call that function in new browser tab.
I made the following changes but didn't worked. Can you please help me on this.
HTML:
<md-button ng-click="ctrl.NewTabClick(item)">View</md-button>
Controller:
vm.newTabClick = function(item){
$Window.open($location.absURL(), 'blank');
// How do I call vm.ViewClick function after opening the new browser window?
};
This is the old angular JS. Thanks for helping on this.
On workaround you can do in this case is, While opening the page pass query parameter in the URL.
vm.newTabClick = function(item){
// Add `viewLink=true` query parameter with true value
$Window.open($location.absURL() + '&viewLink=true', 'blank');
// Store item in sessionStorage
window.sessionStorage.setItem('item', JSON.stringify(item));
}
And then from the component where you want to call the parameter. You can write below code on $onInit lifecycle hook.
vm.$onInit = function () {
// Inject $routeParams in dependency areay
const storedItem = sessionStorage.getItem('item')
if ($routeParams.viewLink == 'true' && storedItem && storedItem != 'null') {
vm.viewLink(JSON.parse(storedItem));
}
}

How to get ui-sref working inside trustAsHtml?

I have a activity state, and when there are no activities I would like to display a message. So I created a if/else statement that checks if the $scope activities has any content, if not it injects a certain code into the template.
if(!$scope.activities.length){
var empty = function(){
$scope.renderHtml = function (htmlCode) {
return $sce.trustAsHtml(htmlCode);
};
$scope.body = '<div>There are no activities yet, <a ui-sref="home.users">click here to start following some friends!</a></div>';
}
empty()
}
The problem is that ui-sref doesn't work, a normal 'a href` does work though. Are there any solid work arounds for this problem?
To get this work I created a element with ng-show,
%div{"ng-show" => "activitiesHide"}
And this js,
activitiesService.loadActivities().then(function(response) {
$scope.activities = response.data;
if(!$scope.activities.length){
$scope.activitiesHide = response.data
}
})
I place the results from the service in the activities scope, and then check in the js if it has content. If not activate the activitesHide show.

when i click on update button i got data to be updated but it gets cleared when i move to update page in angularjs

$scope.fetchDataForEditInvoice = function (row)
{
var index = $scope.gridOptions.data.indexOf(row.entity);
var InvoiceId = $scope.gridOptions.data[index].InvoiceId;
var status = angularService.FetchDataForEditInvoice(InvoiceId);
status.then(function (invoiceData) {
console.log(invoiceData);
window.location.href = "/Invoice/AddInvoice";
$scope.InvoiceDetails = invoiceData.data.InvoiceDetails;
},
function () {
alert('Error in fetching record.');
})
}
on click of update button i call following function and i got data but how i can assign it to controls on update page
save invoiceData.data.InvoiceDetails in a $rootScope variable. So it will available in all controllers.
$rootScope.InvoiceDetails=invoiceData.data.InvoiceDetails;
inject $rootScope to your controller before using it.
Use routers traversing next page.Refer Single Page Apps with AngularJS Routing]1

Angular: how to call a function after changing state

I am building a small message system. I use tabs in my state (inbox, outbox). Also, i want to sent a message when i click a "contact" link. If i click that link, this should happen:
change state to messages state
open other tab, called "newmsg"
At this moment, this is what i have:
<a ng-click="mailContact()">contact</a>
and i my controller:
$scope.mailContact = function() {
$state.go('root.messages');
$scope.openTab('new');
};
Obviously this is not working, because $scope.openTab('new'); will never execute. The state changes to what i want, but the tab is not opened. I do not have a clue of how to get it done.
Ok, stupid thing was i had an init which opened the "inbox"...
Now i wrote a service which does the trick.
app.factory('msgTabService', ['$rootScope', function($rootScope) {
var msgTabService = {};
var tabname = "inbox";
msgTabService.set = function(tab) {
tabname = tab;
};
msgTabService.get = function() {
return tabname;
};
msgTabService.openTab = function(tab) {
if ($rootScope.currenttab !== tab)
{
$rootScope.currenttab = tab;
msgTabService.set(tab);
}
};
return msgTabService;
}]);
The question may be similar to: Save State of Tab content when changing Route with angularjs and BootStrap Tabs

Why will my twitter widget not render if i change the view in angularjs?

Hi and thanks for reading.
I have a angular app im making and ive stumbled on a problem. set up as so
index.html-
<html ng-app="myApp">
...
<div ng-view></div>
<div ng-include="'footer.html'"></div>
...
</html>
I wont bother putting my routes its pretty simple /home is shows the /home/index.html and so on...
/home/index.html (default view when you come to the site)
<div class="responsive-block1">
<div class="tweet-me">
<h1> tweet me </h1>
</div>
<div class="twitter-box">
<twitter-timeline></twitter-timeline>
</div>
twitter timeline directive
directives.directive("twitterTimeline", function() {
return {
restrict: 'E',
template: '<a class="twitter-timeline" href="https://twitter.com/NAME" data-widget-id="XXXXXXXXXXXXXX">Tweets by #NAME</a>',
link: function(scope, element, attrs) {
function run(){
(!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs"));
console.log('run script');
};
run();
}
};
});
So I have just created a basic twitter directive using the tag from twitter. But when I change the view example to /blog then go back to /home the twitter widget no longer renders at all.
Im also using an $anchorScroll and if i jump to anyway on the page with this the widget also disappears. Any info would be great thanks.
See this post: https://dev.twitter.com/discussions/890
I think that you may be able to get the widget to re-render by calling
twttr.widgets.load().
If you find that this does not work, you will need to wrap this code into $timeout in your controller:
controller('MyCtrl1', ['$scope', '$timeout', function ($scope, $timeout) {
$timeout = twttr.widgets.load();
}])
To build on Sir l33tname's answer:
In services declaration:
angular.module('app.services', []).
service('tweetWidgets', function() {
this.loadAllWidgets = function() {
/* widgets loader code you get when
* declaring you widget with Twitter
* this code is the same for all widgets
* so calling it once will reference whatever
* widgets are active in the current ng-view */
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
};
this.destroyAllWidgets = function() {
var $ = function (id) { return document.getElementById(id); };
var twitter = $('twitter-wjs');
if (twitter != null)
twitter.remove();
};
});
Then in controller declarations:
angular.module('app.controllers', []).
controller('view_1_Controller', tweetWidgets) {
// load them all
tweetWidgets.loadAllWidgets();
}).
controller('view_2_Controller', tweetWidgets) {
// now destroy them :>
tweetWidgets.destroyAllWidgets();
});
Now whenever you leave view #1 to go to view #2, your controller for view #2 will remove the widgets associated with view #1 and when you return to view #1 the widgets will be re-instatiated.
The problem is because when Angular switches views the script tag that was originally inserted is not removed from the document. I fixed this on my own website by removing the Twitter script element whenever my Twitter timeline directive is not in the view. See the code below with comments.
function (scope, el, attrs) {
el.bind('$destroy', function() {
var twitterScriptEl = angular.element('#twitter-wjs');
twitterScriptEl.remove();
});
// function provided by Twitter that's been formatted for easier reading
function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0], p = /^http:/.test(d.location) ? 'http' : 'https';
// If the Twitter script element is already on the document this will not get called. On a regular webpage that gets reloaded this isn't a problem. Angular views are loaded dynamically.
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = p + "://platform.twitter.com/widgets.js";
js.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");
}
Basically it's what Loc Nguyen say.
So every time you recreate it you must remove it first.
var $ = function (id) { return document.getElementById(id); };
function loadTwitter() {!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");}
var twitter = $('twitter-wjs');
twitter.remove();
loadTwitter();
Answer by #b1r3k works without problems :
put this in your controller:
$timeout(function () { twttr.widgets.load(); }, 500);
For those trying to load twttr.widgets.load() inside their controller, you will most likely get an error that twttr is not defined AT SOME POINT in your UX, because the async call to load the twitter script may not be completed by the time you controller instantiates and references twttr.
So I created this TwitterService
.factory('TwitterService', ['$timeout', function ($timeout) {
return {
load: function () {
if (typeof twttr === 'undefined') {
(function() {
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');
})();
} else {
$timeout = twttr.widgets.load();
};
}
}
}])
and then call TwitterService.load() inside the controllers that require your widgets. This worked pretty well. It basically just checks if the twttw object exists and if it does, just reload the script... otherwise just reload the script.
Not sure if this is the best implementation, but it seems like all other solutions have edge cases where it will throw an error. I have yet to find one with this alternative.

Resources