PDA

View Full Version : get status rest angularjs


microinfo
06-09-2016, 21:24
services.factory('UsersFactory', function ($resource) {
return $resource('url/users', {}, {
query: { method: 'GET', isArray: true }
})
});
app.controller('UserCreationCtrl', ['$scope', 'UsersFactory', '$location',
function ($scope, UsersFactory, $location) {

$scope.createNewUser = function () {
UsersFactory.create($scope.user);
}
}]);

Tramite un servizio rest mi scarico la lista di utenti in formato json e la stampo a video. Vorrei sapere come posso recuperare lo status di risposta della richiesta per sapere se è andata a buon fine o meno. Ho creato un json con campo stato (0 o 1) e descrizione.
Grazie

71106
06-09-2016, 21:49
Secondo me $resource introduce piu' difficolta' che altro, con $http (https://docs.angularjs.org/api/ng/service/$http) hai una Promise e quindi e' facilissimo:


$http.get('url').then(function (response) {
// OK, i dati sono in response.data
}).catch(function () {
// errore
});

71106
06-09-2016, 21:51
Inoltre ti consiglio di eliminare il campo di status dal formato JSON, e' un antipattern. Se il server deve restituire un errore faglielo restituire tramite HTTP status, altrimenti restituisci direttamente i dati JSON.

Tieni presente che un file JSON non deve necessariamente essere un oggetto. Array, numeri, stringhe, e altri valori semplici sono di per se' valori JSON validi.

microinfo
06-09-2016, 22:16
quindi in pratica come dovrei modificare il mio service senza stravolgere il codice?
per il codice di errore non ho capito bene come fare, io dovrei caricare una tabella con il json ricevuto, se c'è un errore avrei pensato di lanciare un alert con l'errore...

71106
07-09-2016, 11:56
quindi in pratica come dovrei modificare il mio service senza stravolgere il codice? Boh. :Prrr:


per il codice di errore non ho capito bene come fare, io dovrei caricare una tabella con il json ricevuto, se c'è un errore avrei pensato di lanciare un alert con l'errore... L'alert va mostrato alla quarta riga del mio snippet di cui sopra:


$http.get('url').then(function (response) {
// OK, i dati sono in response.data
}).catch(function (response) {
alert(response.statusText);
});

microinfo
07-09-2016, 19:36
ok, volendo testare $http sulla get, ovvero il servizio che mi scarica i dati per popolare la tabella html, cambio da cosi':
(mi sto basando su un esempio preso in rete funzionante)
file controller.js

app.controller('UserListCtrl', ['$scope', 'UsersFactory', '$location',
function ($scope, UsersFactory, $location) {

$scope.users = UsersFactory.query(); //chiama nel service.js il return $resource
}]);

in:


app.controller('UserListCtrl', ['$scope', 'UsersFactory', '$location',
function ($scope, UsersFactory, $location, $http) {

$scope.users = function(){
$http.get('url').then(function (response) {
return response.data; //mi aspetto che nello scope users avrò il json su cui applicare ng-repeat per popolare la tabella
}).catch(function (response) {
alert(response.statusText);
});
}]);

ho provato a cambiare in questo modo, ma la tabella non si carica con i dati e dalla console del browser non vedo errori.
Dove sbaglio?

71106
08-09-2016, 01:10
Prova così:


app.controller('UserListCtrl', function ($scope, $http) {
$http.get('url').then(function (response) {
$scope.users = response.data;
}).catch(function (response) {
alert(response.statusText);
});
});



Una nota interessante: ciò che da (presumo) inesperto hai cercato di fare, ossia assegnare una Promise a un campo dello scope, non è del tutto aberrato, ma ha un suo senso. Le promise sono ancora una tecnologia giovane, ma in EcmaScript 7 sarà possibile fare cose di questo genere:


app.controller('UserListCtrl', function ($scope, $http) {
try {
$scope.users = (await $http.get('url')).data;
} catch (response) {
alert(response.statusText);
}
});


Che però sarebbe sconsigliabile per altri motivi (renderebbe sincrono il flusso di esecuzione del costruttore del controller, ergo bloccherebbe il caricamento della pagina finchè la richiesta HTTP non viene conclusa).

microinfo
08-09-2016, 09:30
in app.controller però in realtà ho anche altre funzioni, tipo questa:

// callback for ng-click 'createUser':
$scope.createNewUser = function () {
$location.path('/user-creation');
};

in questo codice come l'aggiungo?
app.controller('UserListCtrl', function ($scope, $http) {
$http.get('url').then(function (response) {
$scope.users = response.data;
}).catch(function (response) {
alert(response.statusText);
});
});

devo per forza creare $scope.users = function(){ no?

microinfo
08-09-2016, 13:07
ho risolto, il problema era l'url:
$scope.utenti = function(){
$http({
method: 'GET',
url: 'url'
}).then(function successCallback(response) {
$scope.lista = response.data;
}, function errorCallback(response) {
//alert("errore");
//alert(response.status);
alert(JSON.stringify(response, null, 4));
})
//$scope.lista =MacrosFactory.query();
};


$scope.utenti(); //viene lanciata per caricare la fx

ok, adesso ho alcuni dubbi:
1) e se volessi passare un parametro nell'url, per generare una get filtrata?
ho aggiunto un textbox con pulsante, come posso passarlo alla funzione per accodarlo all'url?
2)nella errorCallback e nella successCallback vorrei visualizzare un alert carino tipo bootstrap alert success e danger, come posso fare? dovrei innescare un div e poi nasconderlo?

71106
08-09-2016, 13:25
devo per forza creare $scope.users = function(){ no? No, anzi, non devi crearla. Non insozzare lo scope con elementi che non usi nel markup. Lo scope serve solo a rendere degli elementi visibili alle espressioni interpolate nel markup.



ho risolto, il problema era l'url: [...] Questo:

$http({
method: 'GET',
url: 'url',
})

e' esattamente equivalente a questo:

$http.get('url')



1) e se volessi passare un parametro nell'url, per generare una get filtrata?
ho aggiunto un textbox con pulsante, come posso passarlo alla funzione per accodarlo all'url? Qual e' il problema? l'URL e' una stringa, la generi a piacere.

Cosa ti impedisce di fare ad esempio cosi':

$http.get('users/' + id)

?



2)nella errorCallback e nella successCallback vorrei visualizzare un alert carino tipo bootstrap alert success e danger, come posso fare? dovrei innescare un div e poi nasconderlo? Non usare i componenti JavaScript di Bootstrap perche' con Angular non funzionano. Usa invece AngularUI Bootstrap (https://angular-ui.github.io/bootstrap/).

Qui ci sono gli esempi di come usare le modals: https://angular-ui.github.io/bootstrap/#/modal

E qui gli alert: https://angular-ui.github.io/bootstrap/#/alert

microinfo
08-09-2016, 15:25
si ma +id non posso metterlo a mano, volevo sapere come passarglielo a partire dalla form html della pagina...

71106
08-09-2016, 17:18
si ma +id non posso metterlo a mano, volevo sapere come passarglielo a partire dalla form html della pagina... Binda il controllo a un campo dello scope tramite ng-model (https://docs.angularjs.org/api/ng/directive/ngModel) come faresti normalmente. Usa la "dot rule" per evitare problemi.

microinfo
08-09-2016, 21:29
umm non so come fare perchè la tabella viene caricata dalla:
$scope.utenti(); (vedi sopra)
quando viene lanciato il controller.
poi nella pagina html carico la tabella con ng-repeat su utenti

per fare come dici dovrei passare un parametro alla fx utenti(codice) ma poi non so come lanciarlo :s

71106
08-09-2016, 22:05
Markup:


<form>
<input type="text" ng-model="id"/>
<button ng-click="update()">Aggiorna</button>
</form>
<div ng-repeat="user in users track by $index">{{user}}</div>



Controller:


app.controller('UserListController', function ($scope, $http) {
$scope.update = function () {
delete $scope.users;
$http.get('users/' + id).then(function (response) {
$scope.users = response.data;
});
};
});

microinfo
09-09-2016, 11:44
ok grazie :)
ancora un altro dubbio, ho messo un pulsantino vicino ogni riga della tabella che al click mi apre una pagina per update della riga.
La pagina viene cambiata con $routeprovider, ma vorrei che i campi della tabella(3) vengano popolati nella finestra di edit.
Come posso riempire i 3 inputbox con i campi della riga selezionata?
Ho pensato che cambiando pagina perdo lo scope è vero?
Forse devo creare le modali?

71106
09-09-2016, 12:43
Il router di Angular cambia l'URL ma non la pagina. Le app in AngularJS sono a pagina singola. Non so come stai implementando il tutto ma non dovresti perdere lo scope.

Mettere l'interfaccia di modifica in una modal di AngularUI e' una cosa che puoi sicuramente fare e non escluse l'uso del router, cioe' puoi fare in modo che il router associ un URL alla modal.

Piccola correzione riguardo al markup del mio post precedente: per gestire il click del bottone ho usato ng-click su un elemento <button>, ma in realta' e' molto meglio usare ng-submit sulla form, cosi':


<form ng-submit="update()">
<input type="text" ng-model="id"/>
<input type="submit" value="Aggiorna"/>
</form>

microinfo
09-09-2016, 13:15
si infatti al centro della pagina principale apro la griglia con la tabella, poi cliccando sul pulsante della riga, apro al posto della pagina con la griglia, la pagina di updata.

adesso come faccio a popolare i capi tipo :
<input type="text" style="min-width: 100%" class="form-control" id="inputCodice" placeholder="Inserisci il codice (Obbligatorio)" ng-model="macro.macro_entity_code"/>


con il codice della righa che ho cliccato?
e il riferimento alla specifica riga come lo prendo?

71106
09-09-2016, 13:21
Il metodo open delle modal (vedi documentazione (https://angular-ui.github.io/bootstrap/#/modal)) ti permette di specificare un oggetto di opzioni e tra le varie opzioni e' possibile specificare uno scope. Specifica lo scope associato alla riga della tabella e assicurati che contenga un qualche riferimento ai dati della riga cliccata.

microinfo
09-09-2016, 15:11
per quanti riguarda l'utilizzo delle modali, ho creato:
$scope.openEditModal = function() {
alert("entro il modal");
var modalInstance = $modal.open({
templateUrl: 'pag/upd_record_utente.html',
//controller: 'UserListCtrl',
resolve: {
items: function () {
return $scope.items;
}
}
})
};

ma quando la chiama con ng-click=openEditModal() mi dice che open non è definito, per quale motivo?

Altrimenti trono ad usare il routeprovider e cambiare pagina, ma resta da capire come portarsi lo scope da caricare nella pagina

71106
09-09-2016, 15:20
Cos'e' "$modal"?

Il metodo e' presente nel servizio $uibModal che devi iniettare tramite dependency injection. Qua c'e' il Plunker dell'esempio riportato dalla documentazione: https://plnkr.co/edit/NeX82nSM84n3VH6jPlvr?p=preview

$uibModal e' iniettato alla seconda riga di example.js.

microinfo
09-09-2016, 15:54
umm non ci riesco, ho iniettato nella pagina html animation e sanitize bootrstrap ui ma mi da errore su $$minErr, ma quante cose vuole XD
mi sa che ci rinuncio

71106
09-09-2016, 16:08
Ao', non me sembra difficile:


var app = angular.module('Example', ['ui.bootstrap']);

app.controller('ExampleController', function ($uibModal) {
$uibModal.open({
// ...
});
});



Se non funziona questo vuol dire che non hai incluso UI Bootstrap correttamente.

microinfo
09-09-2016, 16:14
no non basta solo quello, si porta dietro un sacco di librerie come animation di angular :(

wabbe poi ci provo con calma, nel frattempo ti chiedo un altra cosa:
dopo la success di $http visualizzo un msg di alert e setto il msg e lavisibilità del div:
controller:

$scope.successTextAlert = "Lista aggiornata";
$scope.showSuccessAlert = true;

html:
<div class="container-fluid">
<div class="alert alert-success" ng-show="showSuccessAlert">
<button type="button" class="close" data-ng-click="switchBool('showSuccessAlert')">×</button> <strong>Messaggio: </strong> {{successTextAlert}}
</div>
<div class="alert alert-danger" ng-show="showDangerAlert">
<button type="button" class="close" data-ng-click="switchBool('showDangerAlert')">×</button> <strong>Messaggio: </strong> {{dangerTextAlert}}
</div>


il problema è che quando chiudo la pagina ad esempio di inserimento utente per poi tornare tramite routeprovider sulla pagina della griglia, il messaggio non appare. come se non riesce ad acchiappare ng-show del div che si trova nella index

microinfo
13-09-2016, 15:19
nessuno può aiutarmi? non capisco perchè non funziona.
la pagina è composta da una index al cui interno si aprono queste finestre tramite routeprovider. Adesso se in una di queste lancio questo msg da visualizzare, prima di chiudersi dovrebbe riuscire a chiamare il div nella index principale e quindi visualizzare il msg...

71106
13-09-2016, 17:45
Posta codice, cosi' non si capisce niente.

microinfo
14-09-2016, 12:35
La pagina principale è una index.html al cui interno si aprono delle pagine esterne con <div ng-view></div>

nel controller di una pagina esterna che verrà aperta nel <div ng-view></div>:

//Scarico la lista
$scope.find = function(){
delete $scope.users;
$http({
method: 'GET',
url: 'url'
}).then(function successCallback(response) {
$scope.lista = response.data;
$scope.successTextAlert = "Lista aggiornata";
$scope.showSuccessAlert = true;
}, function errorCallback(response) {
$scope.dangerTextAlert = "Errore nell'aggiornamento";
$scope.showDangerAlert = true;
})
};

//Apre e chiude gli alert di segnalazione
$scope.switchBool = function (value) {
$scope[value] = !$scope[value];
};

nella index.html:

<div class="alert alert-success" ng-show="showSuccessAlert">
<button type="button" class="close" data-ng-click="switchBool('showSuccessAlert')">×</button> <strong>Messaggio: </strong> {{successTextAlert}}
</div>
<div class="alert alert-danger" ng-show="showDangerAlert">
<button type="button" class="close" data-ng-click="switchBool('showDangerAlert')">×</button> <strong>Messaggio: </strong> {{dangerTextAlert}}
</div>

Dopo aver lanciato la find non appare nessun msg di errore o successo. Se invece inserisco i div nella pagina esterna appaiono. Se però su questa pagina esterna clicco su un pulsante ad esempio per fare un inserimento di un record, e poi ritorno su una pagina diversa il sistema non funziona (forse perchè cambiando pagina il msg non riesce a vedersi).
Secondo me questi messaggi dovrebbero trovarsi nella index come ho pensato e non nelle singole pagine, ma non funzionano non so perchè.