THE SITUATION:
I need to display a Twitter timeline in my Ionic app. Just that. No further action is needed (login, retweet etc..)
ATTEMPT 1 - SIMPLE EMBED (as in a normal website)
In the view:
<a class="twitter-timeline" href="https://twitter.com/MY_TWITTER" data-widget-id="TWITTER_WIDGET_ID">Tweets by #MY_TWITTER</a>
The script in index.html:
<script>!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");</script>
Is not working. Testing the actual app in the phone, is not showing up. Testing the app in the browser it appears only after refreshing the page.
Bu if i put that same lines of code into a simple angular web app (not a Ionic app) than it works fine.
Why there is this strange behavior? Is ionic related?
ATTEMPT 2 - NGTWITTER
This is the code as explained in this tutorial: http://devdactic.com/twitter-rest-api-angularjs/
The controller:
.controller('TwitterCtrl', function($scope, $ionicPlatform, $twitterApi, $cordovaOauth) {
var twitterKey = 'STORAGE.TWITTER.KEY';
var clientId = 'MY_CLIENT_ID';
var clientSecret = 'MY_CLIENT_SECRET';
var myToken = '';
$scope.tweet = {};
$ionicPlatform.ready(function() {
myToken = JSON.parse(window.localStorage.getItem(twitterKey));
if (myToken === '' || myToken === null) {
$cordovaOauth.twitter(clientId, clientSecret).then(function (succ) {
myToken = succ;
window.localStorage.setItem(twitterKey, JSON.stringify(succ));
$twitterApi.configure(clientId, clientSecret, succ);
$scope.showHomeTimeline();
}, function(error) {
console.log(error);
});
} else {
$twitterApi.configure(clientId, clientSecret, myToken);
$scope.showHomeTimeline();
}
});
$scope.showHomeTimeline = function() {
$twitterApi.getUserTimeline({screen_name: 'MY_TWITTER_FEED'}).then(function(data) {
$scope.home_timeline = data;
});
};
$scope.submitTweet = function() {
$twitterApi.postStatusUpdate($scope.tweet.message).then(function(result) {
$scope.showHomeTimeline();
});
};
$scope.doRefresh = function() {
$scope.showHomeTimeline();
$scope.$broadcast('scroll.refreshComplete');
};
$scope.correctTimestring = function(string) {
return new Date(Date.parse(string));
};
});
The view:
<div class="list">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="My tweet..." ng-model="tweet.message" ng-maxlength="140">
</label>
<button class="button button-small" ng-click="submitTweet()">
Tweet
</button>
</div>
</div>
<ion-refresher on-refresh="doRefresh()"></ion-refresher>
<div ng-show="home_timeline.length == 0">Loading tweets...</div>
<div ng-repeat="entry in home_timeline" class="list card">
<div class="item item-avatar">
<img ng-src="{{entry.user.profile_image_url}}"/>
<h2>{{entry.user.name}}</h2>
<p>{{correctTimestring(entry.created_at) | date:'medium'}}</p>
</div>
<div class="item item-body">
<p ng-bind-html="entry.text"></p>
<img ng-if="entry.extended_entities" ng-src="{{ entry.extended_entities.media[0].media_url }}" style="width: 100%;"/>
</div>
</div>
In this way i can properly see the twitter feed requested plus the possibility to write tweets.
Is not exactly what i want, because it requires the user to login into Twitter and allow the app to be granted access to his twitter account, while i just want to display a twitter feed and nothing more.
Besides, once the twitter section of the app is opened the app is not working anymore as excepted, some links in the menu stop to work.
THE QUESTION:
How can i simply display a twitter timeline inside a Ionic app?
Thank you!
I uploaded a sample project in git hub for Twitter Login in Ionic framework if you have any queries please let me know
Before cloning the project follow these step's :
1)Create a developer project in Twitter Developer console
2)Replace the APPID and APPSECRET in project with your values created in twitter developer console
3)Please write the call back url in twitter developer application as http://tinyurl.com/krmpchb
4)Have a look at README.md file in github
Related
I am making an ionic application and i want to open url in system browser i have installed ionic inappbrowser plugin but i dont know how to use it can some help me with the code.
I want to open {{object.url}} in an browser.
I am using ionic 1
HTML
<body ng-app="newsapp" ng-controller="newscontroller">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Tech Crunch</h1>
</ion-header-bar>
<ion-content>
<section class="list">
<article ng-repeat="object in news">
<a navigate-To="{{object.url}}" class="item item-thumbnail-center">
<img ng-src="{{object.urlToImage}}" height="100%" width="100%">
<h2 class="nowhitespace">{{object.title}}/</h2>
<p class="nowhitespace">{{object.description}}</p>
<h6><i>Published At</i> {{object.publishedAt}}</h6>
</a>
</article>
</section>
<ion-infinite-scroll on-infinite="loadMore()" distance="1%">
</ion-infinite-scroll>
</ion-content>
</ion-pane>u
</body>
app.js
var app = angular.module('newsapp', ['ionic']);
.directive("navigateTo",function($ionicGesture){
return{
restrict: 'A',
link:function($scope,$element,$attr){
var tapharndle = function(e){
var inAppBrowser = window.open{encodeURI{$attr.navigateTo},'_blank','location=yes','toolbar=yes'};
};
var tapGesture = $ionicGesture.on{'tap',tapharndle,$element};
}
}
})
$http({
method: "GET",
url: "https://newsapi.org/v1/articles?source=techcrunch&
sortBy=latest& ``apiKey=90b77760d33d4c76af4c6c53862c9e72"
}) .then(function(newsdata){
angular.forEach(newsdata.data.articles, function(newsarticle) {
$scope.news.push(newsarticle);
});
$scope.lastarticleID= newsdata.data.lastID;
//$scope.news =newsdata.data.articles;
console.log(newsdata);
} )
});
You can use the latest $cordovaInAppBrowser Plugin, which provides a web browser view. It could be used to open images, access web pages, and open PDF files.
Use cordova plugin add cordova-plugin-inappbrowser command from console to add the plugin.
The following configuration of location sets the visibility of URL:
var defaultOptions = {
location: 'no',
clearcache: 'no',
toolbar: 'no'
};
Further instructions are provided on the page of URL given.
I am a beginner at Angular JS and trying to understand this concept. I have a JSON API which consist of product list and have used $hhtp.get to fetch and show the output in the view.
All i want to understand, if the problem statement asks for showing the number of hits/calls made to API in HTML. How to do that.
Here is my sample code
var app = angular.module('FusionApp', []);
app.controller('HomeController', ['$scope', 'displayproducts', function ($scope, displayproducts) {
displayproducts.success(function (data) {
$scope.show = data.products;
//get the product count
$scope.productCount = $scope.show.length;
});
}]);
Here is the HTML view
<div ng-controller="HomeController">
<div class="form-group">
<span ng-model="productCount">Product Count: {{productCount}}</span> |
<span ng-model="apiCount">API Hits:</span>
<p><input type="text" ng-model="name" placeholder="Search by Name" /</p>
</div>
</div>
Appreciate if you guide here. Note displayProducts is the factory service call to return the data
I have an MVC/Angular project. In the shared MVC _layout file I'm creating a UI menu based on JSON from a Web API call. I'm binding that data in the layout file using angular.
The issue I'm having is when I navigate to a new page MVC reloads the _layout file so the $scope.menu variable in the that file no longer exists so my UI menu disappears. The controller then calls the web API call again and repopulates everything so my UI menu is recreated.
Basically I need a way to keep my menu from being reloaded each time I navigate to a new page. Since I'm new to using angular and MVC together I'm not sure of the best approach. Is there a way to keep my $scope.menu variable from being removed when the shared _layout page is reloaded, can I store the JSON in in sessionStorage and recreate the $scope.menu so my UI menu doesn't disappear?
Any help would be appreciated.
//Angular code that creates the menu in the MVC shared _layout file.
<li class="dropdown" ng-repeat="item in menu" menu-item="item">
<a class="dropdown-toggle" role="button" aria-expanded="false" aria-haspopup="true" href="#" data-toggle="dropdown">{{item.Name}} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li>
<div class="dropdowncontainer">
<div class="row" style="padding: 10px; height: 100%">
<div class="col-md-4 col-lg-4 col-sm-12 no-float box-content right" ng-show="item.Places.length" style="height: 100%">
<h4 style="vertical-align:top">Places</h4>
<ul class="list-unstyled">
<li ng-repeat="plc in item.Places">{{plc.Name}}</li>
</ul>
</div>
//Controller that populates the menu with a web api call
mainModule.controller('navCtrl', function ($scope, dataService, modelService) {
if (!$scope.menu) {
$scope.menu = modelService;
dataService.getJson().then(
function (res) {
angular.copy(res.data, modelService);
},
function () {
alert('Error Loading Navigation !');
}
);
}
});
angular.module('main').value('modelService', []);
angular.module('main')
.factory('dataService', ['$http', function ($http) {
return {
getJson: function () {
return $http.get('web api call');
}
};
}]);
I am having some issues in a form I am creating. This form:
<form name="myForm">
<label ng-hide="hide" class="item item-input" >
<span class="input-label">How much minutes?</span>
<input ng-pattern="onlyNumbers" name="number" type="text" ng-model="taskMinutes">
</label>
</form>
Is almost in the middle of the screen but when the user taps on the input field to start typing, the focus is not being correctly executed. The keyboard shows but it is hiding the field. If I start typing, the focus gets executed and the screen moves accordingly. Any tips on how I can fix this?
Update: This is the whole screen:
<ion-view>
<ion-content>
<div class="list">
<label class="item item-input">
<span class="input-label">Task</span>
<input type="text" ng-model="taskInfo">
</label>
<label class="item "> Can this task be measured?
<p>
<ion-checkbox ng-repeat="item in devList"
ng-model="item.checked"
ng-checked="item.checked"
ng-click="change(item)">
{{ item.text }}
</ion-checkbox>
</p>
</label>
<form name="myForm">
<label ng-hide="hide" class="item item-input" >
<span class="input-label">How much minutes?</span>
<input ng-pattern="onlyNumbers" name="number" type="tel" ng-model="taskMinutes">
</label>
</form>
<label class="item" ng-controller="tasksCtrl">
<button ng-disabled="!myForm.number.$valid" class="button button-block button-royal" type="submit" ng-click="addTask()">Add Task</button>
</label>
</div>
This is how I solved it:
NOTE: you have to install cordova keyboard plugin (https://github.com/driftyco/ionic-plugin-keyboard)
var windowHeight = window.innerHeight;
$scope.$on('$ionicView.loaded', function() {
// fallback + warning
var scrollView = {scrollTo: function() { console.log('Could not resolve scroll delegate handle'); }};
var setupKeyboardEvents = function() {
$scope.unbindShowKeyboardHandler = $scope.$on('KeyboardWillShowNotification',
function(info) {
var input = angular.element(document.activeElement);
var body = angular.element(document.body);
var top = input.prop('offsetTop') //+ angular.element(input.prop('offsetParent')).prop('offsetTop');
var temp = angular.element(input.prop('offsetParent'));
var tempY = 0;
while (temp && typeof(temp.prop('offsetTop')) !== 'undefined') {
tempY = temp.prop('offsetTop');
top += tempY;
temp = angular.element(temp.prop('offsetParent'));
}
top = top - scrollView.getScrollPosition().top;
var inputHeight = input.prop('offsetHeight');
var keyboardHeight = info.keyboardHeight;
var requiredSroll = windowHeight - keyboardHeight > top + inputHeight + 11 ? 0 : windowHeight - keyboardHeight - top - inputHeight - 12;
$timeout(function(){ scrollView.scrollTo(0, - requiredSroll || 0, true); });
});
$scope.unbindHideKeyboardHandler = $scope.$on('KeyboardWillHideNotification', function() {
$timeout(function(){ scrollView.scrollTo(0, 0, true); });
});
};
$timeout(function(){
var instances = $ionicScrollDelegate.$getByHandle('your-scroll-handle')._instances;
instances.length && (scrollView = instances[instances.length - 1]);
}).then(setupKeyboardEvents);
});
$scope.$on('$destroy', function(){
$scope.unbindShowKeyboardHandler();
$scope.unbindHideKeyboardHandler();
});
and on application run:
window.addEventListener('native.keyboardshow', keyboardShowHandler);
window.addEventListener('native.keyboardhide', keyboardHideHandler);
function keyboardShowHandler(info){
//alert('Keyboard height is: ' + e.keyboardHeight);
console.log("KeyboardWillShowNotification: " + JSON.stringify(info));
$rootScope.$broadcast('KeyboardWillShowNotification', info);
}
function keyboardHideHandler(info){
$rootScope.$broadcast('KeyboardWillHideNotification', info);
}
and in the template:
<ion-content scroll-handle="your-scroll-handle">
I was having this exact issue yesterday!
Each of the elements on the page had lots of different padding declarations that were conflicting and this broke my form.
Please try removing all styling from the page to see if this fixes it. If it does, add back the styling element-by-element to pinpoint which one is breaking your form.
Hope this helps!
Solved for ionic V1. Just add the fixed as below.
Add "delegate-handle" in the template file.
<ion-content class="padding" overflow-scroll="false" delegate-handle="myInput">
then add function on input field for animate when keyboard open.
<input type="text" id="user" ng-model="user" ng-focus="scrollUP(); keyboardFocus('dnsInput');">
Add the injectable dependency inside the controller
angular.module('starter.user', []).controller('userCtrl', function($scope, $state, $http, $ionicScrollDelegate) {
....
$scope.scrollUP = function () {
if ( app.isAndroid() ) {
document.querySelector("#user").scrollIntoView(false);
}
}
$scope.keyboardFocus=function(handleValue){
if ( app.isAndroid() ) { //check for android platform
$timeout(function(){
$ionicScrollDelegate.$getByHandle(handleValue).scrollBottom();
}, 500);
}
}
});
Make sure to include the ionic keyboard latest version. currently, I used "com.ionic.keyboard": "2.2.1",
For native scrolling, Add the code in app.js
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$ionicConfigProvider.platform.android.scrolling.jsScrolling(true);
.....
}
Enjoy..
The way that I found was to add the class hide-on-keyboard-open of ionic in all components that doesn't uses the keyboard. So this way I do not need to scroll the page cause with this components hidden I can see all I need to do with the keyboard open.
Without Using Any Plugin
This worked for me and currently using in more than 10 apps
NOTE : Please specify reason in comment For Vote Down
Just Add style="height: 400px;" in ion-content Its height Of
keyboard
<ion-view view-title="My Page">
<ion-content>
Hello!
<div style="height: 400px;"></div>
</ion-content>
</ion-view>
Logic explanation : In Phone or Tablet
<ion-view> Is not Scrollable
But
<ion-content> Is Scrollable
So when you scroll its <ion-content> that scrolls and <ion-view> is DEAD , STIFF Never scrolls
I am currently developing an application that uses Cordova, I use the framework with Onsenui AngularJs and library rn-lazy
My problem is that I try to make my list of image loads, only loads 3 images at once out yet they all charge.
How to ensure that the loading of images is done by 3 of 3 works scroll the phone ?
Template list items
<div ng-controller="QueryRequest">
<div class="loader">
CHARGEMENT
<ons-icon icon="refresh" spin="true"></ons-icon>
</div>
<div data-ng-init="ListItem();">
<ons-list>
<ons-list-item class="topcoat-list__item__line-height ons-list-tweets" ng-repeat=" item in tweets ">
<ons-row class="list-tweet">
<!-- <img ng-src="{{item.Tweet.media_url}}" class="img-response"> -->
<ons-col class="div-image-responsive image-list" ng-click="showLightBox(item.Tweet.media_url)" rn-lazy-background="item.Tweet.media_url" rn-lazy-loaded-class="loaded" rn-lazy-loader="#loader" rn-lazy-loading-class="loading"></ons-col>
<ons-col class="twitter-infos item tabs tabs-secondary tabs-icon-left" size="20">
<ons-button class="btn-custom rating-poll" ng-click="rating('like', item.Tweet.id)" type="large--quiet"></ons-button>
</ons-col>
</ons-row>
</ons-list-item>
</ons-list>
<i class="icon-thumbs-up"></i>
<ons-button class="btn-custom rating-poll" ng-click="rating('dislike', item.Tweet.id)" type="large--quiet"></ons-button>
<i class="icon-thumbs-down"></i>
<ons-button class="btn-custom" ng-click="shareThis(item.Tweet.media_url)" type="large--quiet"></ons-button>
<i class="icon-share"></i>
<p class="tweeter">
<a href="https://twitter.com/{{item.Tweet.username}}" pg-in-app-browser-link="">
#{{item.Tweet.username}}
</a>
</p>
<rating-dialog class="{{modalType}}" show="modalShown" width="100%"></rating-dialog>
<p ng-bind-html="message">{{message}}</p>
</div>
</div>
Controller
App.controller('QueryRequest', function ($scope, $resource, storage, $stateParams, queryRequest, $window, $sce, $rootScope) {
"use strict";
$scope.ListItem = function () {
var request = queryRequest.get();
var tweets = storage.get("twitter_" + request);
if (tweets !== null) {
if (!storage.isObsolete()) {
$scope.tweets = tweets;
} else {
var Tweets = $resource(Clooder.getTweets(request));
Tweets.get({}, function ($query) {
storage.set("twitter_" + request, $query.tweets, 0);
$scope.tweets = storage.get("twitter_" + request);
App.ajaxStop();
});
}
} else {
var Tweets = $resource(Clooder.getTweets(request));
Tweets.get({}, function ($query) {
storage.set("twitter_" + request, $query.tweets, 0);
$scope.tweets = storage.get("twitter_" + request);
App.ajaxStop();
});
}
});
You may have better luck with this library: https://github.com/GeneralElectric/winchjs
Images are loaded based on their own awareness of if they are in the view portal of the screen. There is a lot less (or none) code needed to accomplish your task.
I used jQuery in my AngularJS controller to wait image loading. The following links would help you.
jQuery event for images loaded