Output image from RESTful Service Angular - angularjs

I am new to Angular so to get to grips with it I have been working with a Dummy RESTful service. Right now I have managed to pull the image URL and then push it into an array.
I would like to output this array as an image when the "ng-click" directive is fired.
Any guidance or help would be much appreciated.
<p ng-click="outputImageData()">click me</p>
<ul>
<li ng-repeat="photo in photos">
{{ image }}
</li>
</ul>
myApp.factory('getImages', function($http) {
var imageService = {
async: function(id) {
var promise = $http.get('https://jsonplaceholder.typicode.com/photos/1').then(function(response) {
return response.data;
})
return promise;
}
};
return imageService;
});
myApp.controller("outputImages", function($scope, getImages) {
var photos = [];
$scope.outputImageData = function() {
getImages.async().then(function(data) {
var photoId = data.url;
photos.push(photoId);
console.log(photos);
})
}
});
Thanks

I've been using angularjs but generally as a developer, I'm just started so bear with me, please.
I think something like this would work:
<p ng-click="updateImageData()">click me</p>
<ul>
<li ng-repeat="photo in photos">
<img src="{{photo.url}}">
</li>
</ul>
myApp.factory('getImages', function($http) {
var imageService = {
async: function() {
var promise = $http.get('https://jsonplaceholder.typicode.com/photos/');
return promise;
}
};
return imageService;
});
myApp.controller("outputImages", function($scope, getImages) {
$scope.photos = [];
$scope.updateImageData = function() {
getImages.async(photoId).then(function(data) {
$scope.photos = data;
console.log(photos);
})
}
});

Related

Initialise AngularJS service - factory on the document load

Sorry for a very stupid question but I just started working with AngularJS and OnsenUI.
I have got a service to get a data from SQLite:
module.factory('$update', function () {
var update = {};
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM event_updates', [], function (tx, results) {
var rows = results.rows;
update.items = [];
if (!rows.length) {} else {
for (var index = 0; index < rows.length; index++) {
update.items.push({
"title": rows.item(index).title,
"date": rows.item(index).date,
"desc": rows.item(index).desc
});
}
}
}, function (error) {
console.log(error);
});
});
return update;
});
And a controller which is using the data:
module.controller('UpdatesController', function ($scope, $update) {
$scope.items = $update.items;
});
As soon as my page is loaded the content is not displayed and I need to click twice to call a page with the code below to see the content:
<ons-list ng-controller="UpdatesController">
<ons-list-item modifier="chevron" class="list-item-container" ng-repeat="item in items" ng-click="showUpdate($index)">
<div class="list-item-left">
</div>
<div class="list-item-right">
<div class="list-item-content">
<div class="name">{{item.title}}</div> <span class="desc">{{item.desc}}</span>
</div>
</div>
</ons-list-item>
</ons-list>
Can anybody help how can I initialise the controller as soon as page is loaded with all content. Sorry if it is a stupid question but I am really struggling. Appreciate your help a lot.
You could store the result of the request in the factory and retrieve those instead.
module.factory('$update', function () {
var update = {};
var requestValues = function(){ // store the results of the request in 'update'
// Your db.transaction function here
}
var getUpdates = function(){ // retrieve the values from 'update'
return update;
}
return{
requestValues : requestValues,
getUpdates : getUpdates
}
});
And then in you controller:
module.controller('UpdatesController', function ($scope, $update) {
$update.requestValues();
$scope.items = $update.getUpdates();
});
You could then get the values from anywhere in you solution (by using $update.getUpdates) without having to make an extra http request.

How to check image exist on server or not in angular js?

I have a recent article section where i need to validate whether image is exist or not on server.
I try some tutorial it validate properly but it does not return any value to my ng-if directive.
Here is my recent article section:-
<div ng-controller="RecentCtrl">
<div class="col-md-3" ng-repeat="items in data.data" data-ng-class="{'last': ($index+1)%4 == 0}" bh-bookmark="items" bh-redirect>
<div class="forHoverInner">
<span class="inner">
<span class="defaultThumbnail">
<span ng-if="test(app.getEncodedUrl(items.bookmark_preview_image))" style="background-image: url('{{app.getEncodedUrl(items.bookmark_preview_image)}}'); width: 272px; height: 272px; " class="thumb" variant="2"></span></span></span> </div>
</div></div>
Here is my recent article controller:-
app.controller('RecentCtrl', function($scope, $http, $rootScope, RecentArticleFactory,$q) {
$scope.test = function(url) {
RecentArticleFactory.isImage(url).then(function(result) {
return result;
});
};
})
Here is recent aricle factory code:-
app.factory("RecentArticleFactory", ["$http", "$q", function ($http, $q) {
return {
isImage: function(src) {
var deferred = $q.defer();
var image = new Image();
image.onerror = function() {
deferred.resolve(false);
};
image.onload = function() {
deferred.resolve(true);
};
image.src = src;
return deferred.promise;
},
}
})
But
ng-if="test(app.getEncodedUrl(items.bookmark_preview_image))" does not return any value
Any Idea?
Thats because it is async due to deferred. Try calling the test function and binding the result value to a field in scope.
First, trigger the test function via $watch:
$scope.$watch("data.data", function() {
for(var i = 0; i < $scope.data.data.length; i++) {
var items = $scope.data.data[i];
$scope.test(items);
}
})
Then change your test function as follows:
$scope.test = function(items) {
items.isImageAvailable= false;
RecentArticleFactory.isImage(items.bookmark_preview_image).then(function(result) {
items.isImageAvailable= result;
});
};
})
Finally, you can use this in your view as:
<span ng-if="items.isImageAvailable" ...></span>
Of course you also need to call app.getEncodedUrl in between. But as I could not see, where app is defined, I omitted this. But the conversion is nevertheless necessary.

AngularJS and UI-Router: keep controller loaded

I am building a web application for our customer support. One of the needs is to be able to keep multiple tickets opened at the same time.
I was able to do the first part easily using a tabulation system and UI-Router.
However, with my current implementation, each time I change active tab, the previously-current tab is unloaded, and the now-current tab is loaded (because it was unloaded with a previous tab change).
This is not at all the expected behavior. I've already spent a couple of days trying to find a way to achieve this, without any luck.
The closest thing I was able to do is to use the multiple views system from UI-Router, but I need multiple instance of the same view to keep in memory (if multiple tickets are opened, they all are on the same view, with the same controller, but a different scope)
Here's my current implementation:
supportApp.js:
var app = angular.module("supportApp", ["ui.router", "ui.bootstrap"]);
app.config(function($stateProvider, $urlRouterProvider, $httpProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.decorator('d', function(state, parent){
state.templateUrl = generateTemplateUrl(state.self.templateUrl);
return state;
})
.state("main", {
abtract: true,
templateUrl: "main.html",
controller: "mainController"
})
.state("main.inbox", {
url: "/",
templateUrl: "inbox.html",
controller: "inboxController"
})
.state('main.viewTicket', {
url: '/ticket/{id:int}',
templateUrl: "viewTicket.html",
controller: "ticketController"
})
;
});
mainController.js: (handles other stuff, minimal code here)
app.controller("mainController", function($rootScope, $http, $scope, $state, $interval){
// Tabs system
$scope.tabs = [
{ heading: "Tickets", route:"main.inbox", active:false, params:{} }
];
var addTabDefault = {
heading: '',
route: null,
active: false,
params: null,
closeable: false
};
$rootScope.addTab = function(options){
if(!options.hasOwnProperty('route') || !options.route)
{
throw "Route is required";
}
var tabAlreadyAdded = false;
for(var i in $scope.tabs)
{
var tab = $scope.tabs[i];
if(tab.route == options.route && angular.equals(tab.params, options.params))
{
tabAlreadyAdded = true;
break;
}
}
if(!tabAlreadyAdded)
{
$scope.tabs.push($.extend({}, addTabDefault, options));
}
if(options.hasOwnProperty('active') && options.active === true)
{
$state.go(options.route, options.hasOwnProperty('params')?options.params:null);
}
};
$scope.removeTab = function($event, tab){
$event.preventDefault();
if($scope.active(tab.route, tab.params))
{
$scope.go($scope.tabs[0].route, $scope.tabs[0].params);
}
$scope.tabs.splice($scope.tabs.indexOf(tab), 1);
};
$scope.go = function(route, params){
$state.go(route, params);
};
$scope.active = function(route, params){
return $state.is(route, params);
};
$scope.$on("$stateChangeSuccess", function() {
$scope.tabs.forEach(function(tab) {
tab.active = $scope.active(tab.route, tab.params);
});
});
});
main.html:
<div class="container-fluid" id="sav-container">
<div class="row-fluid">
<div class="col-lg-2">
<form role="form" id="searchForm" action="#">
<div class="form-group has-feedback">
<input class="form-control" type="search" />
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</form>
</div>
<div class="col-lg-10" id="support_main_menu">
<ul class="nav nav-tabs">
<li ng-repeat="t in tabs" ng-click="go(t.route, t.params)" ng-class="{active: t.active, closeable: t.closeable}" style="max-width: calc((100% - 128px) / {{tabs.length}});">
<a href class="nav-tab-text">
<button ng-show="t.closeable" ng-click="removeTab($event, t)" class="close" type="button">×</button>
<span>{{t.heading}}</span>
</a>
</li>
</ul>
</div>
</div>
<div class="row-fluid">
<div class="tab-content" ui-view></div>
</div>
</div>
It seems to me that what I ask is pretty standard, but I sadly couldn't find any usefull thing on the Internet
The basic idea is to store state (i.e. list of tickets) in a service as opposed to a controller. Services hang around for the life of the application. There are some articles on this. I'm still developing my approach but here is an example:
var RefereeRepository = function(resource)
{
this.resource = resource; // angular-resource
this.items = []; // cache of items i.e. tickets
this.findAll = function(reload)
{
if (!reload) return this.items;
return this.items = this.resource.findAll(); // Kicks off actual json request
};
this.findx = function(id)
{
return this.resource.find({ id: id }); // actual json query
};
this.find = function(id) // Uses local cache
{
var itemx = {};
// Needs refining
this.items.every(function(item) {
if (item.id !== id) return true;
itemx = item;
return false;
});
return itemx;
};
this.update = function(item)
{
return this.resource.update(item);
};
};
refereeComponent.factory('refereeRepository', ['$resource',
function($resource)
{
var resource =
$resource('/app_dev.php/referees/:id', { id: '#id' }, {
update: {method: 'PUT'},
findAll: {
method: 'GET' ,
isArray:true,
transformResponse: function(data)
{
var items = angular.fromJson(data);
var referees = [];
items.forEach(function(item) {
var referee = new Referee(item); // Convert json to my object
referees.push(referee);
});
return referees;
}
},
find: {
method: 'GET',
transformResponse: function(data)
{
var item = angular.fromJson(data);
return new Referee(item);
}
}
});
var refereeRepository = new RefereeRepository(resource);
// Load items when service is created
refereeRepository.findAll(true);
return refereeRepository;
}]);
So basically we made a refereeRepository service that queries the web server for a list of referees and then caches the result. The controller would then use the cache.
refereeComponent.controller('RefereeListController',
['$scope', 'refereeRepository',
function($scope, refereeRepository)
{
$scope.referees = refereeRepository.findAll();
}
]);

angularjs ng-repeat filter on static value not working

I can't figure out why the code below is not filtering just the values with unique_id of "027". I've tried it as a string as well '027'...
JSON file:
[
{
"unique_id":"027",
"title":"How Speed Relates to Energy",
"state":"NY",
"state_id":"1.S2.3a"
}
]
Here my controller:
var abApp = angular.module('abApp', []);
abApp.factory('abData', function($http, $q) {
var deffered = $q.defer();
var data = [];
var abData = {};
abData.async = function() {
$http.get('/data/ab_activities.json')
.success(function(ab) {
data = ab;
deffered.resolve();
});
return deffered.promise;
};
abData.data = function() {
return data;
};
return abData;
});
abApp.controller("abEE", function(abData, $scope) {
var abApp = this;
abData.async().then(function(ab) {
abApp.alignments = abData.data();
});
})
Here's my HTML:
<div ng-controller="abEE as ee">
<ul>
<li ng-repeat="align in ee.alignments | filter:{unique_id : 027} ">
{{align.unique_id}} - {{align.state}}, {{align.state_id}}
</li>
</ul>
</div>
you need to correct your html markup like this, as in your JSON unique_id is a string:
<div ng-controller="abEE as ee">
<ul>
<li ng-repeat="align in ee.alignments | filter:{unique_id : '027'} ">
{{align.unique_id}} - {{align.state}}, {{align.state_id}}
</li>
</ul>

How to watch a deferred service property?

If I have the following simple controller & service.
<div ng-controller="MessagesCtrl">
<ul>
<li ng-repeat="message in data.messages">
{{ message }}
</li>
</ul>
</div>
myApp.factory('Data', function () {
var _messages = [];
return {
messages: _messages,
getMessages: function() {
$http.get('/messages').then(function(response) {
_messages = response.data;
});
}
};
});
function MessagesCtrl($scope, Data) {
$scope.data = Data;
$scope.data.getMessages();
}
I would expect the messages model to auto-update when the AJAX request completes and fills the object, however it does not. How is this supposed to work? (I'm sort of asking what the best practice is for this structure).
Edit - working solution:
<div ng-controller="MessagesCtrl">
<ul>
<li ng-repeat="message in data.messages">
{{ message }}
</li>
</ul>
</div>
myApp.factory('Data', function () {
return {
getMessages: function() {
var _this = this;
$http.get('/messages').then(function(response) {
_this.messages = response.data;
});
}
};
});
function MessagesCtrl($scope, Data) {
$scope.data = Data;
$scope.data.getMessages();
}
I'm fairly certain you have a JavaScript issue here and not an AngularJS related issue. Let's remove the AngularJS related code and leave just the JavaScript piece:
function factory() {
var _messages = [];
return {
messages: _messages,
getMessages: function() {
_messages = [1, 2, 3, 4];
}
}
}
> var test = factory();
undefined
> test.messages
[]
> test.getMessages()
undefined
> test.messages
[]
test.messages points to the origin _messages array whereas later on _messages is getting changed but test.messages is not.

Resources