How to Capture Enter View Event in Directive in Ionic/Angular

How to Capture Page View Enter Event in Directive in Ionic 1 Angular 2?

Directives do not get the normal $ionicView.enter events like controllers. You have to register for the parent view event using $ionicParentView.enter.

$scope.$on("$ionicParentView.enter", function (event, data) {
    // will fire enter event in your directive              
});

Note: Do not import $ionicParentView into your directive, this will cause your code to break.

Good luck!

How to Find Visible HTML Element by class in JavaScript

How to Find Visible HTML Element by class in JavaScript?

We can use the same logic jQuery uses with this code:

element.offsetWidth > 0 && element.offsetHeight > 0;

You can simply go through the list of your class elements to find the one currently displayed.

for (var i = 0; i < document.getElementsByClassName('myclass').length; i++) 
{
   if (document.getElementsByClassName('myclass')[i].offsetWidth > 0 &&
       document.getElementsByClassName('myclass')[i].offsetHeight > 0) 
       {
           //found the visible element of class 'myclass'
            break;
       }
}

Creating and Opening PDF on Ionic 1 on iOS

Recently I ran into an issue using the PdfMake on Ionic 1 on iOS. It works fine on the browser with a simple download or open command but not on the actual device.

Install the cordova libraries:

cordova.plugins.fileOpener2
cordova-plugin-file

Download the pdfmake javascript files and include them in your index.html

<script src='build/pdfmake.min.js'></script>
<script src='build/vfs_fonts.js'></script>

The code:

  var self = this ; // defined on top of the file

  var docDefinition = { content: 'This is an sample PDF printed with pdfMake' };

            self.pdfObj = pdfMake.createPdf(docDefinition);

            if (window.cordova) {
                self.pdfObj.getBuffer(function (buffer) {
                    var blob = new Blob([buffer], { type: 'application/pdf' });
                    // Save the PDF to the data Directory of our App
                    $cordovaFile.writeFile(cordova.file.dataDirectory, 'myletter.pdf', blob, { replace: true }).then(function () {
                        // Open the PDf with the correct OS tools
                        cordova.plugins.fileOpener2.open(cordova.file.dataDirectory + 'myletter.pdf', 'application/pdf');
                    })
                });
            }

Setup Config.xml

In your config.xml make sure you have the file settings

<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="iosPersistentFileLocation" value="Library" />

Ionic HTTP posts don’t work on iOS

I ran into this strange problem today where HTTP requests stopped working on iOS alone. Even though I have the latest Ionic CLI, my project was running Ionic 1 still.

To solve this http error I removed this plugin:

ionic cordova plugin remove cordova-plugin-ionic-webview

And added this to config.xml:

<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />

Probably a bit unsafe to allow everything but had to get it working again.
If this doesn’t work for you try to also remove the iOS platform and re-add it.

good luck~

How To Embed and Open PDF files in Ionic App on iOS

This is a solution for storing and opening pdf files inside your app for offline use.

  cordova.plugins.fileOpener2.open(
        cordova.file.applicationDirectory + 'www/img/sample.pdf',
        'application/pdf',
        {
          error: function (e) {
            console.log('Error status:'+e.status+'- Error message:'+ e.message);
          },
          success: function () {
            console.log('file opened successfully');
          }
        }
      );

Opening the pdf should be fairly simple using the cordova.plugins.fileOpener2 plugin, but I ran into a strange issue because my app name in the config.xml contained a space such as: <name>My App</name>. This caused the iOS to misread the file path. Removing this space in the app name fixed the file path on iOS.

I put the sample pdf doc in the ionic project under my images folder www/img/sample.pdf.

Good luck!

MQTT.js Download for Ionic/Angular Client Use

What is MQQT.js

MQTT.js is a client library for the MQTT protocol, written in JavaScript for node.js and the browser.

You can download the client/browser version here:

-> browserMqtt.js

Usage

You can then use mqtt.js in the browser with the same API that nodeJS uses.

<html>
<head>
  <title>test Ws mqtt.js</title>
</head>
<body>
<script src="./browserMqtt.js"></script>
<script>
      var client = mqtt.connect() // you add a ws:// url here
      client.subscribe("mqtt/demo")

      client.on("message", function (topic, payload) {
        alert([topic, payload].join(": "))
        client.end()
      })

      client.publish("mqtt/demo", "hello world!")
    </script>
</body>
</html>

Source: https://github.com/mqttjs/MQTT.js

How To Auto-Generate Ionic iOS App Logo & Splash Screen

Icon Source Image

Save an icon.png, icon.psd or icon.ai file within the resources directory at the root of the Cordova project. The icon image’s minimum dimensions should be 192×192 px, and should have no rounded corners. Note that each platform will apply it’s own mask and effects to the icons.

For example, iOS will automatically apply it’s custom rounded corners, so the source file should not already come with rounded corners.

What I do here is replace the icon.png in resources folder with a new 1024×1024 PNG file. And then run the following command:

$ ionic resources --icon

Splash Screen Source Image

Save a splash.png, splash.psd or splash.ai file within the resources directory at the root of the Cordova project. Splash screen dimensions vary for each platform, device and orientation, so a square source image is required the generate each of various sizes.

The source image’s minimum dimensions should be 2208×2208 px, and its artwork should be centered within the square, knowing that each generated image will be center cropped into landscape and portrait images.

The splash screen’s artwork should roughly fit within a center square 1200x1200px.

What I do here is replace the splash.png in resources folder with a new 2208×2208 PNG file. And then run the following command:

$ ionic resources --splash

This will generate all the needed icons and splash screens for all your targeted devices.

Generating Icons and Splash Screens

To generate both icons and splash screens, follow the instructions above and run:

$ ionic resources

Source: Ionic Docs

Angular ng-show in ng-repeat not working in Ionic

The official Angular Docs Page for ng-show does not explain how to use this within a repeater.

The ngShow directive shows or hides the given HTML element based on the expression provided to the ngShow attribute. The element is shown or hidden by removing or adding the .ng-hide CSS class onto the element. The .ng-hide CSS class is predefined in AngularJS and sets the display style to none (using an !important flag).

The common mistake when using ng-show in repeater (ng-repeat) is the usage of angular brackets {{}}

  1. This example won’t work if the div is in a repeater:

<div ng-show="{{value == othervalue}}">

Use This Instead:

<div ng-show="value == othervalue">

Usually the app won’t complain and there won’t be any errors in the console, which makes debugging this edge case so difficult.

How To Use Ionic & Angular q Promises?

The Deferred API

A new instance of deferred is constructed by calling $q.defer().

The purpose of the deferred object is to expose the associated Promise instance as well as APIs that can be used for signaling the successful or unsuccessful completion, as well as the status of the task.

Methods

resolve(value) – resolves the derived promise with the value. If the value is a rejection constructed via $q.reject, the promise will be rejected instead.

reject(reason) – rejects the derived promise with the reason. This is equivalent to resolving it with a rejection constructed via $q.reject.

notify(value) – provides updates on the status of the promise’s execution. This may be called multiple times before the promise is either resolved or rejected.
Properties

promise – {Promise} – promise object associated with this deferred.

// for the purpose of this example let's assume that variables `$q` and `okToGreet`
// are available in the current lexical scope (they could have been injected or passed in).

function asyncGreet(name) {
  var deferred = $q.defer();

  setTimeout(function() {
    deferred.notify('About to greet ' + name + '.');

    if (okToGreet(name)) {
      deferred.resolve('Hello, ' + name + '!');
    } else {
      deferred.reject('Greeting ' + name + ' is not allowed.');
    }
  }, 1000);

  return deferred.promise;
}

var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
  alert('Success: ' + greeting);
}, function(reason) {
  alert('Failed: ' + reason);
}, function(update) {
  alert('Got notification: ' + update);
});

This code example was taken from Angular Documentation page: https://docs.angularjs.org/api/ng/service/$q

Deferred item content shows up blank on iOS and Safari in Ionic/Angular

Deferred item content shows up blank on iOS and Safari in Ionic/Angular. The item eventually shows up after you interact with it (click or drag).

There seems to be some kind of mystery issue of items not rendering until the user clicks on it. This is only broken in Safari and iOS devices.

The solution I found was to set my div item class to this:

.myItem{
   -webkit-transform: translate3d(0,0,0);
}

I don’t know yet why this fixes it, but it does for me. I originally found the solution thanks to this github issue:

https://github.com/driftyco/ionic/issues/1110

Ionic Issue With ng-click On iOS Firing Twice

There is an issue with ng-click on iOS firing twice in my app testing. After trying all sorts of event.stopPropagation it still didn’t work correctly. The issue might be related to using angular material library in your project.

I finally solved it by adding this to my app.js file

.config(function( $mdGestureProvider ) {
          $mdGestureProvider.skipClickHijack();
  })