我还是相对较新的Angular,我一直在尝试创建一个小应用程序,它可以回答几个问题并挑选一些图片并将其发送到服务器。
当用户选择图像时,我一直在使示波器正确更新时遇到一些问题。或者至少那对我来说似乎是个问题。
我认为问题出在'CreateCtrl'控制器内,可能是'ImageService'和/或'FileService'。
这是下载离子项目的链接...... http://newepicweb.com/beaches/beaches_reporter_public.zip
// app.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'ngIOS9UIWebViewPatch'])
.run(function ($ionicPlatform, $rootScope, $http, $ionicModal) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
$rootScope.loginToken = window.localStorage['token'] ? window.localStorage['token'] : '';
$rootScope.isLoggedIn = false;
if($rootScope.loginToken){
$rootScope.isLoggedIn = true;
}
// Form data for the login modal
$rootScope.loginData = {
email: 'xxxx@xxxxx.com',
password: 'xxxxxxxxx'
};
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $rootScope
}).then(function (modal) {
$rootScope.loginModal = modal;
if(!$rootScope.isLoggedIn){
$rootScope.login();
}
});
// Triggered in the login modal to close it
$rootScope.closeLogin = function () {
$rootScope.loginModal.hide();
};
// Open the login modal
$rootScope.login = function(){
$rootScope.loginModal.show();
}
var successfulLogin = function (response){
$rootScope.isLoggedIn = true;
$rootScope.loginToken = response.data.token;
window.localStorage['token'] = response.data.token;
$rootScope.closeLogin();
}
var failedLogin = function(response){
alert('Bad credentials. Please try again.');
}
// Perform the login action when the user submits the login form
$rootScope.doLogin = function () {
$http.post('www.site.com', $rootScope.loginData).then(successfulLogin,failedLogin);
};
});
})
.config(function ($stateProvider, $urlRouterProvider, $ionicConfigProvider, $compileProvider) {
$ionicConfigProvider.backButton.text('').icon('ion-chevron-left').previousTitleText(false);
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.welcome', {
url: '/welcome',
views: {
'menuContent': {
templateUrl: 'templates/welcome.html'
}
}
})
.state('app.reports', {
url: '/reports',
views: {
'menuContent': {
templateUrl: 'templates/reports.html'
}
}
})
.state('create', {
url: '/create',
abstract: true,
templateUrl: 'templates/create.html',
controller: 'CreateCtrl'
})
.state('create.setup', {
url: '/setup',
views: {
'createContent': {
templateUrl: 'templates/create/setup.html'
}
}
})
.state('create.step1', {
url: '/step1',
views: {
'createContent': {
templateUrl: 'templates/create/flag.html'
}
}
})
.state('create.step2', {
url: '/step2',
views: {
'createContent': {
templateUrl: 'templates/create/water-color.html'
}
}
})
.state('create.confirm', {
url: '/confirm',
views: {
'createContent': {
templateUrl: 'templates/create/confirm.html'
}
}
})
.state('create.photos', {
url: '/photos',
views: {
'createContent': {
templateUrl: 'templates/create/photos.html'
}
},
controller: 'CreatePhotosCtrl'
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/welcome');
});
// services.js
angular.module('starter.services', ['ngCordova'])
.factory('FileService', function($cordovaFile, $q){
function makeId() {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 5; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
function saveFile(fileName){
console.log('in fileservice save file');
var defer = $q.defer();
var name = fileName.substr(fileName.lastIndexOf('/') + 1);
var namePath = fileName.substr(0, fileName.lastIndexOf('/') + 1);
var newName = makeId() + name;
try {
$cordovaFile.copyFile(namePath, name, cordova.file.dataDirectory, newName).then(function() {
console.log('in fileservice file copy file then');
defer.resolve(newName);
});
} catch (e){
console.log('fail save file');
defer.reject();
}
return defer.promise;
};
return {
saveFile: saveFile
};
})
.factory('ImageService', function($cordovaCamera, $q) {
var images = [];
function optionsForType(type) {
var source;
switch (type) {
case 0:
source = Camera.PictureSourceType.CAMERA;
break;
case 1:
source = Camera.PictureSourceType.PHOTOLIBRARY;
break;
}
return {
destinationType: Camera.DestinationType.FILE_URI,
sourceType: source,
allowEdit: false,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
};
function getImages(){
return images;
}
function saveImage(imageName){
console.log('in image save image');
console.log(imageName);
images.unshift(imageName);
}
function addImage(type) {
var defer = $q.defer();
var options = optionsForType(type);
try {
$cordovaCamera.getPicture(options).then(function(imageUri) {
console.log('in get picture then');
defer.resolve(imageUri);
});
} catch (e) {
defer.reject();
}
return defer.promise;
};
return {
addImage: addImage,
saveImage: saveImage,
getImages: getImages
};
});
// controllers.js
angular.module('starter.controllers', ['ngCordova'])
.controller('AppCtrl', function ($scope, $rootScope) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//$scope.$on('$ionicView.enter', function (e) {
//});
})
.controller('CreateCtrl', function ($scope, $ionicPlatform, $ionicHistory, $location, $state, $cordovaDevice, $ionicActionSheet, ImageService, FileService) {
var date = new Date;
var currentHour = date.getHours();
var year = date.getFullYear();
var month = date.getMonth(); // beware: January = 0; February = 1, etc.
var day = date.getDate();
if (currentHour < 10) {
var postDate = month + '/' + day + '/' + year + ' 10:00 AM';
} else {
if (currentHour > 16) {
var postDate = month + '/' + ( 1 + day ) + '/' + year + ' 10:00 AM';
} else {
var postDate = month + '/' + day + '/' + year + ' 4:00 AM';
}
};
$scope.images = ImageService.getImages();
$scope.backwards = function () {
$ionicHistory.goBack();
};
$scope.nextPage = function (path) {
$state.go(path);
};
$scope.skipPage = function (path, field) {
$scope.reportBuilding[field] = null;
console.log($scope.reportBuilding);
$state.go(path);
};
$scope.reportBuilding = {
id: null,
postDate: postDate,
beach: {
id: 1,
name: 'Clearwater Beach',
city: {id: 2, name: 'Clearwater'},
county: {id: 1, name: 'Pinellas County'}
},
flag: null,
waterSurfaceTemp: null,
waterColor: null,
respiratoryIrritation: null,
deadFish: null,
jellyfish: null,
debris: null,
windDirection: null,
surf: null,
surfType: null,
surfHeight: null
};
$scope.addImage = function(type){
$scope.hideSheet();
ImageService.addImage(type).then(function (imageName) {
console.log('in image service then');
FileService.saveFile(imageName).then(function(newImage){
console.log('in file save image then', newImage);
ImageService.saveImage(newImage);
var imgJsonStr = angular.toJson($scope.images, true);
console.log('Save Image 1', imgJsonStr)
$scope.$apply();
console.log('Images length', $scope.images.length);
console.log('Save Image 2', imgJsonStr)
});
});
};
$scope.addMedia = function () {
console.log('images : ' + $scope.images.length)
$scope.hideSheet = $ionicActionSheet.show({
buttons: [{text: 'Take photo'}, {text: 'Photo from library'}],
titleText: 'Add Image',
cancelText: 'Cancel',
buttonClicked: function (index) {
$scope.addImage(index);
}
});
};
$scope.urlForImage = function(imageName){
return cordova.file.dataDirectory + imageName;
}
});
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="lib/Ionicons/css/ionicons.min.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<script type="text/javascript">
window.onerror = function(message, url, lineNumber) {
console.log("Error: "+message+" in "+url+" at line "+lineNumber);
}
</script>
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="lib/ngCordova/dist/ng-cordova.js"></script>
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
<script src="js/ngIOS9UIWebViewPatch.js"></script>
</head>
<body ng-app="starter">
<ion-nav-view></ion-nav-view>
</body>
</html>
// create.html
<ion-header-bar class="bar bar-header">
<h1 class="title">BEACH CONDITION REPORTING SYSTEM</h1>
</ion-header-bar>
<ion-header-bar class="bar bar-subheader">
<img src="img/mote-logo.png" class="logo center-block" />
</ion-header-bar>
<ion-nav-view name="createContent"></ion-nav-view>
// templates / photos.html
<ion-view>
<ion-content class="hidden-backbutton">
<div class="transparent-overlay">
<button class="button button-full button-energized" ng-click="addMedia()">
Add image
</button>
<br><br>
<ion-scroll direction="y">
<div class="card" ng-repeat="image in images track by $index" >
<div class="item image">
<img ng-src="{{urlForImage(image)}}" class="full-image" />
</div>
<div class="item item-divider">
<button class="button button-assertive button-block button-clear icon icon-right ion-close">Remove Photo</button>
</div>
</div>
</ion-scroll>
</div>
</ion-content>
<ion-footer-bar align-title="left" class="bar-stable">
<div class="buttons">
<button class="button button-clear icon ion-chevron-left icon-left" ng-click="backwards()"> Back</button>
</div>
<div class="title">1 of 8</div>
<div class="buttons">
</div>
</ion-footer-bar>
</ion-view>
XCode控制台日志输出
2015-10-20 14:56:14.399 beaches_reporter[4704:1733175] Apache Cordova native platform version 3.8.0 is starting.
2015-10-20 14:56:14.400 beaches_reporter[4704:1733175] Multi-tasking -> Device: YES, App: YES
2015-10-20 14:56:14.411 beaches_reporter[4704:1733175] Unlimited access to network resources
2015-10-20 14:56:14.623 beaches_reporter[4704:1733175] [CDVTimer][keyboard] 0.474036ms
2015-10-20 14:56:15.335 beaches_reporter[4704:1733175] [CDVTimer][splashscreen] 711.232007ms
2015-10-20 14:56:15.418 beaches_reporter[4704:1733175] [CDVTimer][file] 83.101034ms
2015-10-20 14:56:15.419 beaches_reporter[4704:1733175] [CDVTimer][TotalPluginStartup] 796.294987ms
2015-10-20 14:56:15.771 beaches_reporter[4704:1733175] Resetting plugins due to page load.
2015-10-20 14:56:16.239 beaches_reporter[4704:1733175] Finished load of: file:///var/mobile/Containers/Bundle/Application/848C1D5C-5F75-4BD1-821D-6203CF17E2FA/beaches_reporter.app/www/index.html#/app/welcome
2015-10-20 14:56:23.694 beaches_reporter[4704:1733175] images : 0
2015-10-20 14:56:29.187 beaches_reporter[4704:1733175] in get picture then
2015-10-20 14:56:29.187 beaches_reporter[4704:1733175] in image service then
2015-10-20 14:56:29.188 beaches_reporter[4704:1733175] in fileservice save file
2015-10-20 14:56:29.343 beaches_reporter[4704:1733175] THREAD WARNING: ['File'] took '144.152100' ms. Plugin should use a background thread.
2015-10-20 14:56:29.373 beaches_reporter[4704:1733175] in fileservice file copy file then
2015-10-20 14:56:29.373 beaches_reporter[4704:1733175] in file save image then uxwHQcdv_photo_011.jpg
2015-10-20 14:56:29.374 beaches_reporter[4704:1733175] in image save image
2015-10-20 14:56:29.374 beaches_reporter[4704:1733175] uxwHQcdv_photo_011.jpg
2015-10-20 14:56:29.374 beaches_reporter[4704:1733175] Save Image 1 [
"uxwHQcdv_photo_011.jpg"
]
2015-10-20 14:56:29.374 beaches_reporter[4704:1733175] Images length 1
2015-10-20 14:56:29.374 beaches_reporter[4704:1733175] Save Image 2 [
"uxwHQcdv_photo_011.jpg"
]
答案 0 :(得分:1)
要完成很多代码但是如果强制$ scope.apply更新图像数组会怎样?
$scope.addImage = function(type){
$scope.hideSheet();
ImageService.addImage(type).then(function (imageName) {
console.log('in image service then');
FileService.saveFile(imageName).then(function(newImage){
console.log('in file save image then', newImage);
ImageService.saveImage(newImage);
var imgJsonStr = angular.toJson($scope.images, true);
console.log('Save Image 1', imgJsonStr)
$scope.$apply(function() {
$scope.images[] = imgJsonStr;
});
console.log('Images length', $scope.images.length);
console.log('Save Image 2', imgJsonStr)
});
});
};