Ionic Angular Cordova $ scope不会更新服务更新

时间:2015-10-20 18:13:27

标签: javascript angularjs cordova ionic

我还是相对较新的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()"> &nbsp;&nbsp;&nbsp; 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"
    ]

1 个答案:

答案 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)
                });
            });
        };