I am trying to integrate intercom.io in my AngularJS application.
The script has some parameters to configure before the full loading:
<script id="IntercomSettingsScriptTag">
window.intercomSettings = {
// TODO: The current logged in user's email address.
email: "john.doe#example.com",
// TODO: The current logged in user's sign-up date as a Unix timestamp.
created_at: 1234567890,
app_id: "95b20cd5364bab3a2136e252d2862b8136aabe7e"
};
</script>
<!-- Init script -->
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://static.intercomcdn.com/intercom.v1.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}};})()</script>
I tried to use {{data.email}} to replace the email but unfortunately, the init script get loaded before the intercomSettings. ng-cloak is not very useful for me because it has been designed only for presentation purposes.
I am not sure in which direction I should look for.
To test my code: http://plnkr.co/edit/2PJNLukBx0cTOPZXNwqs?p=preview
You should get a little question mark at the bottom right of the window if it works.
I'm not sure if you already found a solution, but you should take a look on this:
https://github.com/maxiperezc/angular-intercom
it basically wrapped intercom script into angular, so you can use within your application using directives.
This is an improved version of https://github.com/gdi2290/angular-intercom - they removed some unnecessary code
I updated angular-intercom to the latest intercom api if you're still interested. The service has been simplified for the user with a better way of handling async script loading
https://github.com/gdi2290/angular-intercom
Related
I have created a sidemenu based app, in that after login I am displaying a number of tasks. If I click on the task it will redirect to the task details page, in that page I can update the tasks.
So after updating a task I need to go back to the previous task list page. I am using $ionicHistory.goBack(); to go back.
My problem is after come back, I need to refresh the task list i.e. updated task should not be there in the task list. How can I refresh/reload the task list?
If you bind your task to a tasks array, which will be used in the task list page, it should be automatically updated.
But the question is about not displaying, newly added tasks (still my previous suggestion should work) if not, performance reasons ionic views are cached, So when you come back to the previous view it doesn't go through the normal loading cycle. But you 2 options
1 - disable the caching by using <ion-view cache-view="false" view-title="My Title!"> in your ion-view, but this is not a very elegant solution. read more
2 - use ionRefresher (my preferred). read more here
https://github.com/angular-ui/ui-router/issues/582
according to #hpawe01 "If you are using the current ionicframework (ionic: v1.0.0-beta.14, angularjs: v1.3.6, angular-ui-router: v0.2.13), the problem with the not-reloading-controller could be caused by the new caching-system of ionic:
Note that because we are caching these views, we aren’t destroying scopes. Instead, scopes are being disconnected from the watch cycle. Because scopes are not being destroyed and recreated,controllers are not loading again on a subsequent viewing.
There are several ways to disable caching. To disable it only for a single state, just add cache: false to the state definition.
This fixed the problem for me (after hours of reading, trying, frustration).
For all others not using ionicframework and still facing this problem: good luck!"
Hope this helps.
You can also listen to ionic events such as $ionicView.enter on $scope and trigger the code that refreshes the list if you haven't bound your list as #sameera207 suggested.
EG:
// List.controller.js
angular.module('app')
.controller('ListController', ['$scope', function($scope) {
// See http://ionicframework.com/docs/api/directive/ionView/ for full events list
$scope.$on('$ionicView.enter', function() {
_someCodeThatFetchesTasks()
.then(function(tasks) {
$scope.tasks = tasks;
});
});
});
Bear in mind that it's not the most proper way (if proper at all) and if you do this you certainly have a design flaw. Instead you should share the same data array via a factory or a service for example.
For your task you can also use ion-nav-view.
It is well documented. And if you are using now Ionic 2 beta you can use some of the view lifecyle hooks like onPageWillLeave() or onPageWillEnter(). I just faced the same problem and defined a refresh() function, but the user had to click on a button to actually update the view. But then I found:
https://webcake.co/page-lifecycle-hooks-in-ionic-2/
You just have to import the Page and NavController module and also define it in the constructor. The you can use for example onPageWillEnter(), which will always invoke when you go again to a view:
onPageWillEnter() {
// Do whatever you want here the following code is just to show you an example. I needed it to refresh the sqlite database
this.storage.query("SELECT * FROM archivedInserates").then((data) = > {
this.archivedInserates =[];
if (data.res.rows.length > 0) {
for (var i = 0; i < data.res.rows.length; i++) {
this.archivedInserates.push({userName:data.res.rows.item(i).userName, email:
data.res.rows.item(i).email});
}
}
},(error) =>{
console.log("ERROR -> " + JSON.stringify(error.err));
});
}
With ionic beta 8 the lifecylcle events changed their names. Check out the official ionic blog for the full list of the lifecycle events.
if you are building data driven app then make sure use $ionicConfigProvider.views.maxCache(0);in your app.config so that each review can refresh for more details read this http://ionicframework.com/docs/api/provider/$ionicConfigProvider/
I have started to use angularjs and now am following a tutorial about angularjs with angularfire. In the tutorial there is a section to learn how to use child_added
angular.module('firebaseApp').service('MessageService', function(FBURL, $q, $firebase) {
var messageRef = new Firebase(FBURL).child('messages');
var fireMessage = $firebase(messageRef).$asArray();
return {
childAdded: function childAdded(limitNumber, cb) {
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
},
and main controller :
MessageService.childAdded(5, function(addedChild){
$timeout(function() {
$scope.messages.push(addedChild);
});
});
When I use the code, chrome developer tools is giving an error :
TypeError: undefined is not a function
adressing .$on in MessageService and .childadded in controller.
This is a video tutorial and I can see him working like this. I checked many answers but could not find a way. My best shot is I guess different versions of angularjs and angularfire. But that did not help me either. Can you help me to solve it?
Thank you in advance.
I thought I'd offer a bit of clarity on the topic for those who are taking this tutorial on tutsplus. First, we should pay attention to the versions of firebase and angularfire that we are using, compared to what the instructor is using. This might seem obvious, but there are many out there who fail to realize it. Whenever watching a tutorial, you should always check the version of ANY package you are using. This world of software moves really fast, and up-to-date tutorials are a luxury.
Pay attention to your bower.json file in your project. Note the version of the following lines:
"firebase": "~2.0.4",
"angularfire": "~0.9.0"
You can see here the version of the dependencies I used. Chances are, you were like me, and your version will differ from what you find in the teacher's version. The instructor offers his source files on the course main page. Download those files, which should be titled SourceFiles_RTWebAppAngularFirebase.zip. Once downloaded, open it, and you will see a list of packaged zip files contained in a file called Firebase Source. Find lesson-16-angularfire.zip, and also open it. A folder titled "Firebase" should be provided, and there you will find the instructor's app that he created during the tutorial. Check out his bower.json file, and check it against what you have. According to what I found, both versions of firebase and angularfire were vastly different. This means only one thing: we have some reading to do.
Go here and check out the releases of AngularFire: https://github.com/firebase/angularfire/releases
Scroll down, and read the release notes of v0.8.0. A very important note is found here.
$on() and $off() no longer exist. Similar functionality can be obtained with $watch() but should be discouraged for trying to manually manage server events (manipulation should be done with data transformations through $extendFactory() instead).
Obviously now, we understand that we can't follow blindly in the instructor's footsteps. We have to try mimicking his app's functionality. Reading what I posted above, we can use $watch to obtain similar functionality. However, I honestly tried to make this work, and the functionality that $watch delivers is not exactly the functionality we are trying to achieve. Ideally, we should synchronize our empty messages array $scope.messages with $firebase(messageRef).$asArray(). That wouldn't be as fun though.
The route I took was this: I looked at what cb.call() was doing, which is the following
MessageService.childAdded(function(addedChild) {
$scope.messages.push(addedChild);
});
This call back function pushes an object created from cherry picked values obtained from a snapshot returned from a 'child_added' event. The real leverage here is the snapshot, which is provided by the $firebase module itself with Firebase.on(). If you read the docs for the "Child_Added" event, it says
This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added. The DataSnapshot passed into the callback will reflect the data for the relevant child
The DataSnapshot returned for every "initial" child at this location, is what initially populates the list of messages. This means that we can change this:
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
back to this:
messageRef.on('child_added', function(snapshot) {
var val = snapshot.val();
cb.call(this,
user: val.user,
text: val.text,
name: snapshot.key()
});
});
The messages should populate again on the front page. Your code should be stable enough as well to follow the instructor during the remainder of the Refactor lesson.
In my angularjs application, I need to get some data from remote, and during the time, I showed a "loading data ..." text on the page.
The page is basically like this:
<div ng-show="remoteData">
{{remoteData}}
</div>
<div id="loading" ng-hide="remoteData">
Loading data, wait ...
</div>
And in the angularjs code:
function SomeCtrl($scope, $http) {
$http.get("/...").success(function(data) {
$scope.remoteData = data;
});
}
But how can I test it with protractor?
Since we use mocking files provided in local server in e2e test, the $http.get(...) part will run really fast, and when I try to check the "loading" div, it always be hidden since the data has already loaded.
If there any way to test it?
In my application, I decided to implement the following scheme:
backend, when run in development mode, adds an additional middleware which is looking at the value of the cookie header
if the cookie header named __km_delay is present, it contains a number with the delay set in ms. This middleware will sleep for the given amount of time before handling control to the next middleware
At the same time, I use the following with Protractor:
browser.manage().addCookie('__km_delay', millis, '/')
And when I'm done with the test, I invoke:
browser.manage().deleteCookie('__km_delay')
This has the advantage of not having to modify the Angular app logic in any way for testing.
If you're wondering why I chose cookie and not another HTTP header, is because I found no way of setting an extra header with Protractor. And cookie is a header anyway ;)
BTW, I use similar thing to test 5xx server responses.
I basically want to use tel tag to make a phone call.
<a class="callButton" href="tel: {{phoneno}}"></a>
I am using $compileProvider to remove unsafe tag which comes by default, It works perfectly fine post 1.0.4v of angularjs. However below this version it doesnt work. Can anyone suggest how to implement this feature using angular version 1.0.4 or below?
Here is the sanitizing code which I am using in js file
app.config(['$compileProvider', function ($compileProvider) {
$compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
}
Assume I have already defined app variable.
P.S. This is an enhancement for particular app which basically works below 1.0.4v
Thanks
Add this to your scripts after angular is loaded.
I asume your on 1.1.5, but change to whatever you need the version to be.
http://code.angularjs.org/1.1.5/angular-sanitize.min.js
Example:
sanitizeSomething = function(string) {
return $sanitize(string);
};
sanitizedString = sanitizeSomething(string);
I have no idea, how to explain this properly, but i try my best.
I have worked with flowplayer in jquery mobile (with multipage).
I have about 20 video sourced from database.
Now the problem:
I don't want all the videos start loading, when i start the video.
I have tried to make javascript to start correct video with '' tag, but it needs two clicks to start video.
Here is link i'm using (sorry, some forms are in finnish) http://www.rakentaja.fi/test/mobv/3mobvid.asp
Don't bother to go in front page, because i haven't finished those sites.
just pick any of the links and watch what happens.
Please, use google chrome, it's only browser which is the only one what works.
Thank you!
Avoid using inline Javascript functions, do it this way.
$('a.ui-link').on('click', function() {
aloitavid(61,'Valloxsuodpuhdvaihto');
});
Since each link has different parameters; you need to add those to the <a> link attributes and then pull them to be used in your function.
Update
You could do the below. Save video parameters as an attribute vlink, then read parameters and pass them to your function aloitavid(). Example here.
HTML
start video
Code
$('a.ui-link').on('click', function () {
var vlink = $(this).attr('vlink').split(",");
var value1 = vlink[0];
var value2 = vlink[1];
aloitavid(value1,value2)
});
This results
value1: 60
value2: Valloxyleistailmanvkoneenhuollosta
Try to put links to hardcoded
Back
if it's posible.
That won't be nice, but it works.