Search This Blog

Tuesday 29 March 2016

CDVPlugin not found/Mach -o error while archiving or exporting ipa of ionic/cordova apps

When you have a plugin written in swift in your ionic/cordova app, it builds but when archive or export it returns CDVPlugin not found error. Follow the steps below to resolve the issue.
Note: Run all ionic commands build, add etc using sudo only.
Ex: sudo ionic build ios
As we are moving code from windows to mac, permissions are arising.
Steps:
  1. In terminal change give permissions
$ Sudo chown –R:staff <your folder path>
$  sudo chown –R 777 *
  1. Now go to Target-> build settings
    1. Look for RunPaths and add below if it’s not there:
$(inherited)@executable_path/Frameworks
@executable_path/Frameworks

  
    1. Now look for Header Search Paths and add the below:
$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include

    1. Set Enable Bit code to No

    1. In Deployment section, clear Install Owner and Groups

  1. Now go to Build Phases and
    1. Empty Embedded Frameworks, (if any swift plugins are there)

  1. Go to general and in frameworks add UIKit if not added


Sunday 20 March 2016

Markers with different colors in ionic using angularJS, Centering the map

for getting maps in maps in ionic project follow steps in this post

now lets see
1. how to center the map to your screen
2. place markers of different colors
3. increase bounds of your map
4. Show window/message on click of marker

1. Centering the map to current location:
$cordovaGeolocation.getCurrentPosition(options).then(function(position){

var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var mapOptions = {
 center: latLng,
 zoom: 15,
 mapTypeId: google.maps.MapTypeId.ROADMAP

};
                $scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);
});

here getCurrentPositions return the lattitude (lat) and longitude (lon) of my current place.
i will use it in my map options to center it. highlighted above line will set my current location to center my map.

2&3. Place Markers:
lets say i want to place markers in my below lat, lons

var latlons = [{lat:"12.9450362",lon:"77.6970354",title:"msg1"},{lat:"12.9550364",lon:"77.6890356",title:"msg2"},{lat:"12.9950366",lon:"77.6800358",title:"msg3"}];

create a pin to show the marker:

var RedPinColor = "FE7569";
var RedPinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + RedPinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));

var bounds = new google.maps.LatLngBounds(); //for increase/decrease zoom

for (var i = 0; i < markers.length; i++) {
var data = markers[i];
var myLatlng = new google.maps.LatLng(data.lat, data.long);
var marker = new google.maps.Marker({
position: myLatlng,
map: $scope.map,
title: data.title,
icon:RedPinImage,
shadow:pinShadow
});
bounds.extend(myLatlng);
                              $scope.fitBounds(bounds);
}

i am adding bounds which will help me in increase/decrese zoom of my map according to the markers i am adding.

the pin Image can be changed as you need, below are 2 ex:
var GreenPinColor = "69fe75";//"FE7569";
var YellowPinColor = "FFFF00";
var RedPinColor = "FE7569";
var RedPinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + RedPinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
var YellowPinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + YellowPinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
var GreenPinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + GreenPinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
new google.maps.Size(40, 37),
new google.maps.Point(0, 0),
new google.maps.Point(12, 35));

Display window/message on click of markers:
google maps offers a InfoWindow to display message on click of markers created above.

the below line create a infowindow.
var infoWindow = new google.maps.InfoWindow();

now need to bind to click event of marker. let see how to do it in a loop (as most of us need to do in looping always)
var infoWindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();


for (var i = 0; i < markers.length; i++) {
var data = markers[i];
var myLatlng = new google.maps.LatLng(data.lat, data.long);
var marker = new google.maps.Marker({
position: myLatlng,
map: $scope.map,
title: data.title,
icon:RedPinImage,
shadow:pinShadow
});
bounds.extend(myLatlng);

//Attach click event to the marker.
(function (marker, data) {
var infoWindowContent = "<div style = 'width:200px;min-height:40px'>"+"<p>" + data.DisplayName + "</p>"
+ "<button ng-click="+"\""+"MarkerClick('"+data.SensorName+"')"+"\""+">"+"Schedule Pick"+"</button>"+"</div>";
console.log(infoWindowContent);
var compiled = $compile(infoWindowContent)($scope);
// console.log(compiled["body"]);
google.maps.event.addListener(marker, "click", function (e) {
//Wrap the content inside an HTML DIV in order to set height and width of InfoWindow.
infoWindow.setContent(compiled[0]);
infoWindow.open($scope.map, marker);
});
})(marker, data);
$scope.map.fitBounds(bounds);
}
});

after a marker is created, using a function and creating a content to be displayed on its click: infoWindwContent

as angular restricts direct html binding need to compile it before attaching it to my window using $compile service. sometimes if the html is unsafe you may need to use $sce service to bind unsafe html.

use setContent to set create content info window
open actually assigns the map and marker to which this infowindow to be attached


using Google Maps in Ionic/Web project

its a simple two step process

1. to use google maps in your project, you should get a api key from google console
2. install cordova GeoLocationAPI
2. add a div and from javascript bind map to it.

1.Creating API key:
1. go to https://console.cloud.google.com/
2. from the top nav bar  project->create project
3. go to use google api
4. select google maps api for javascript
5. enable it and to get the api key you need credentials to be created
6. click on credentials in the left pane
7. click on create credentials (blue button)
8. click on API Key
9. select android as i was trying for an android app
10. give a name to the key and click create.
11. copy the API key it is required for the next step

2. install GeoLocation plugin
          ionic plugin add cordova-plugin-geolocation
reference: https://www.npmjs.com/package/cordova-plugin-geolocation

3. Adding to your project:
 in your ion-view (can be any html need not be ionic) add a div with an id which wanted to use to load map.
<ion-view view-title="Find Near by Bins" ng-controller="FindNearByViewCtrl">
<ion-nav-buttons side="right">
      <i class="ion-log-out" style="font-size:2.2em" ng-click="doLogout()"></i>
 </ion-nav-buttons>
 <ion-nav-buttons side="left">
      <i class="ion-loop" style="font-size:2.2em" ng-click="doRefresh()"></i>
 </ion-nav-buttons>
<ion-content>
<div id="map" data-tap-disabled="true"></div>
</ion-content>
</ion-view>

in your controllers, add the below piece to bind map to #map.
$cordovaGeolocation.getCurrentPosition(options).then(function(position){
 
var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var latLng1 = new google.maps.LatLng(19.1759668, 72.79504659999998);
console.log(""+position.coords.latitude+"---"+ position.coords.longitude);
var mapOptions = {
 center: latLng1,
 zoom: 15,
 mapTypeId: google.maps.MapTypeId.ROADMAP
};
               $scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);
});

thats it displays google map in your project

toggle buttons with ionic

ionic is for mobile apps and toggle button is a common control which is widely used for yes/no, select/unselect purposes. lets see how to use it.

ionic has a tag called, ion-toggle which is used for showing and handling toggle button events. use this in your html:

<ion-toggle ng-model="checked" 
ng-change="TogglePanel(checked)" class="TransparentBG">
<span ng-class="DynHubStatus" class="CategoryTitle">Air</span>
</ion-toggle>

ng-model: checked is to set true or false
ng-change triggers change event and TogglePanel function will be called on change
by default it comes with white background, use css to change that.
in code behind:
$scope.TogglePanel = function(toStatus){
   //use the event to perform your required events.
}

ng-model checked will be set to true on turning on and to false on turning off the button

Saturday 19 March 2016

Charts with AngularJS/Ionic

angular has plugins which support several kinds of charts. one among them is http://www.chartjs.org/

lets see how to use it:
1. download the package from the above link
2. include css and js
      <link href="css/angular-chart.min.css" rel="stylesheet">
     <script src="js/Chart.min.js"></script>
3. use it in html
    <canvas id="line" class="chart chart-line" data="data" labels="labels" legend="true" options="{showTooltips: false}"></canvas>

initialize values in your controller:
.controller('LineChartCtrl',function($scope){
 
    $scope.labels = ["Jan", "","","Feb","","", "Mar", "","Apr", "May", "Jun", "Jul","Aug","Sep","Oct","Nov","Dec"];
    // $scope.series = ['Series A', 'Series B'];
    $scope.data = [
        [13, 15,12,18,22,24,21,25]
    ];

})

the library also supports gant,bar etc charts follow the above steps to use it.

Sliders with AngularJS/Ionic

angular has growing no.of plugins. it has good  plugin called rzslider. to work with sliders
here is the link to it: https://github.com/angular-slider/angularjs-slider

lets see how to use it:
i want a slider to select a time range of start time to end time, so my slide will look like this:
here is the html:
1. download the package from above link or you can use npm to install to your project folder
2. add the css and js files in header
         <link href="css/rzslider.css" rel="stylesheet">
        <script src="js/rzslider.js"></script>
3. include slide tag in your page
        <rzslider rz-slider-model="minRangeSlider.minValue" rz-slider-                       high="minRangeSlider.maxValue" rz-slider-options="minRangeSlider.options"></rzslider>

mignRangeSlider is initialized in angular code behind.
code:
$scope.minRangeSlider = {
        minValue: 8,
        maxValue: 18,
        options: {
            floor: 0,
            ceil: 24,
            step: 1
        }
    };
thats it. it has several sliders, using the same steps you can use them.

working with DateTimes in nodejs/find difference between two datetimes

this is about playing with DateTimes in NodeJS. Javascript has good no.of datetime functions but to simplify it a bit more we can use moment npm package which offers a rich set of datetime functions.

to install it use  npm install moment --save

sample usage:

var StartTS = moment("Wed Mar 25 2015 01:00:00 GMT",'YYYY-M-DD HH:mm:ss');
var EndTS = moment("Wed Mar 26 2015 12:19:43 GMT",'YYYY-M-DD HH:mm:ss');
the above create dates like 2016-03-24 01:00:00 format.

to find difference between the above two use the below:
var secondsDiff = EndTS.diff(StartTS, 'seconds')

it returns the time difference in seconds. this is simple handy.


connecting to documentdb from nodejs using bluemix/azure

Problem Statement:
I want to connect to documentdb using nodejs run time. i will be receiving a POST request and i have to add time stamp to it and store it in azure's document db.

we need to include a couple of npm packages to get it.
Solution:
--save is important as we need to upload it to azure for hosting. sometimes those npm packages installtion may fail in cloud.

npm install express --save //for expressJS, which exposes services
npm install cfenv --save //for bluemix hosting, if you are hosting in some other cloud it can be ignored
npm install body-parser --save //for reading the received request
npm install documentdb --save //for documentdb functions.
npm install async --save //for making request
npm install moment --save //for dealing with time stamps

then, need to make connections and run queries, here is the code for it.
https://github.com/Azure/azure-documentdb-node use this link to see some samples. first lets see how to list all documents in my collection using queries.

1. Create client
2. create your required query.
3. queryDocuments

var client = new DocumentClient(host, {masterKey: mymasterkey});
//masterKey can be found in your azure document db.
var querySpec = {query: 'SELECT * FROM CTransactions c order by c.TimeStamp desc'};
//i am listing all transactions from my collection in descending order
client.queryDocuments(collLinkTransactions, querySpec).toArray(function (err, results) {
if(err){
handleError(err);
}
else if(results.length==0){
res.end("Not Started");
}
else {
                      //use the data as you want
                 }
});

collLinkTransactions is the url link to my documentdb collection.
i am returning the query result in an array and if no errors and length is>0 i will process it and send to my client.

here is the complete code:
run it using> node app.js
complete can be found here

Create Row every after 2 item in Angular ng-repeat - Ionic Grid/ tiles in ionic

Problem Statement:
i am having my elements which are to be shown in two column tiles. my data binding will be done dynamically from angular code behind. i can divide my row into columns but keeping data into that column in an ng-repeat is the challenge.

solution is simple, use angulars inbuilt variable $even of $index and show column for $index and $index+1 in column 1 and column 2 respectively.

for every even index 2 column will be set with $index and next elements and in odd index loop will not go in. problem solved. below is the sample code

Solution:
<div class="row" ng-repeat="sensors in SecurityDevices" ng-if="$even">
<div class="col col-49" >
<div class="imageIcon">
<img src="/img/devices/fire.png">
</div>
<div class="DeviceName">{{SecurityDevices[$index].Model}}</div>
<div class="FriendlyName">Kids Room</div>
</div>
<div class="col col-49" >
<div class="imageIcon">
<img src="/img/devices/motion.png">
</div>
<div class="DeviceName">{{SecurityDevices[$index+1].Model}}</div>
<div class="FriendlyName">Kids Room</div>
</div>
</div>

maintain two divs same width and height angular/ionic

Problem Statement:
I have two divs and i need to maintain them at some height always. one expands its size decreases based in dynamic content that will be loaded and  the other has to increase/decrease its height accordingly.

my elements are the below:
1. <div round-progress master
max="100"
current="100"
color="green"
bgcolor="#eaeaea"
rounded="true"
clockwise="true"
responsive="true">

</div>

2. 
<div class="item AirDivs AirMeterFill" ng-style="Airstyle">
      <div style="height:30%; background-color: rgba(195, 7, 15, 0.09);border-top: 3px solid     #DC0D29;font-size:smaller;text-align: center;">
<div>poor: 8</div>
<div></div>
</div>

</div>
according to size of 1st element i want to set height of 2nd element using angularJS/Ionic.

Solution:
It can be achieved through angular directives easily. Use below directive to set it

.directive('master',function () { //declaration
  function link(scope, element, attrs) { //scope we are in, element we are bound to, attrs of that element
   scope.$watch(function(){ //watch any changes to our element
 console.log("ht:"+element[0].offsetHeight);
     scope.Airstyle = { //scope variable style, shared with our controller
     height:element[0].offsetHeight-35+'px', //set the height in style to our elements height
     // width:element[0].offsetWidth+'px' //same with width
   };
   });
  }
 return {
  restrict: 'AE', //describes how we can assign an element to our directive in this case like <div master></div
  link: link // the function to link to our element
 };
});


  • i am having a directive called master which can be a element/attribute - defined by restrict
  • i am linking it using my link function, where i will be watching for any change of my master (1st element) 
  • when the height of master changes i am setting ng-style of  my other div.
  • i can get of height of 1st element using offsetHeight html property. 

Refrence: http://www.ngroutes.com/questions/1b1848d/set-height-of-one-div-to-another-div-in-angularjs.html