Двусторонняя привязка данных после вызова Ajax

У меня проблема с двухсторонней привязкой данных AngularJS. Я постараюсь объяснить проблему как можно более четко: у меня есть список имен контактов. Для каждого элемента у меня есть кнопка Изменить. Когда я нажимаю на эту кнопку, я загружаю "полный" контакт из вызова Ajax, а затем я показываю окно с некоторыми полями ввода, связанными с только что полученным контактом ("телефон", "электронная почта" и т. Д.). Это интересная часть представления:

<div>    
    <div class="contact" data-ng-repeat="contact in contacts">
        <span>{{contact.label}}</span>
        <a href="" class="btn btn-xs btn-default" data-ng-click="openContactModal(contact.ID)">
            Edit
        </a>
    </div>
</div>

Нажатие на кнопку "Редактировать" запускает эту функцию (присутствует в контроллере):

var newContact = null;
$scope.openContactModal = function(contactID){  
    newContact = new Contact(contactID);
    newContact.onLoad().then(
        function(){
            //loading OK
            $('#myModal').modal('show');
        },
        function(){
            //loading Error

        }
    );
    $scope.newContact = newContact;
};

Призыв к new Contact(contactID) загружает контакт из базы данных с помощью вызова Ajax. Я открываю модальное окно в конце вызова Ajax (в ожидании обещания AngularJS). В модальном режиме все поля пусты, даже если они связаны с моделью контакта (newContact.phone, newContact.email так далее.). Я уже проверил, что Ajax-вызов работает нормально (печатая полученный JSON). Я полагаю, что мне что-то не хватает в проблеме двустороннего связывания данных. Странный факт, что, если я попытаюсь заполнить пустые модальные поля, newContact Модель хорошо реагирует, как будто двусторонняя привязка данных работает хорошо с точки зрения модели, но не наоборот. Заранее спасибо!

РЕДАКТИРОВАТЬ: это служба, которая получает контакт:

angular.module("app").factory("Contact", ["ContactDBServices", "$q",
    function(ContactDBServices, $q){
        return function(contactID){

            //the contact itself
            var self = this;

            var contactPromise = $q.defer();

            //attributi del contatto
            this.firstName = null;
            this.ID = null;
            this.lastName = null;
            this.phone = null;
            this.fax = null;
            this.mobile = null;
            this.email = null;
            this.web = null;

            //the Ajax call    
            var metacontact = ContactDBServices.find({ID:contactID}, 
                function(){
                    this.ID = contactID;
                    this.firstName = metacontact.contact_name;
                    this.lastName = metacontact.contact_last_name;
                    this.phone = metacontact.contact_phone;
                    this.fax = metacontact.contact_fax;
                    this.mobile = metacontact.contact_mobile;
                    this.email = metacontact.contact_email;
                    this.web = metacontact.contact_web;

                    //!!!THE FOLLOWING PRINTS ARE GOOD!!!!  
                    console.log(this.ID);
                    console.log(this.firstName);
                    console.log(this.lastName);
                    console.log(this.phone);
                    console.log(this.fax);
                    contactPromise.resolve("OK");
                },
                function(){
                    contactPromise.reject("Error");
                }
            );


            this.onLoad = function(){
                return contactPromise.promise;
            };

    }
}]);  

Если я печатаю те же значения в контроллере, все эти значения undefined:

var newContact = null;
$scope.openContactModal = function(contactID){  
    newContact = new Contact(contactID);
    newContact.onLoad().then(
        function(){

            //!!!!!!!!THE FOLLOWING PRINTS ARE ALL UNDEFINED!!!!
            console.log(newContact.firstName);
            console.log(newContact.lastName);
            console.log(newContact.phone);
            console.log(newContact.fax);

            $('#myModal').modal('show');
        },
        function(){
            //loading Error

        }
    );
    $scope.newContact = newContact;
};

Это странно. Кажется, что-то вроде проблемы с синхронизацией:-/, чтобы быть точным, вот пример модальной части:

<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <h2>Contact</h2>
            </div>
            <div class="modal-body">
                <label>
                    Name
                    <input class="form-control" id="new_contact_name" data-ng-model="newContact.firstName" placeholder="Name">
                </label>
                <!-- ...and so on -->
            </div>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary" data-dismiss="modal" data-ng-click="createContact()">Crea</button>
        </div>
    </div>
</div>

1 ответ

Решение

В конце концов я нашел ошибку. Это была моя ошибка, и она принадлежит не AngularJS, а Javascript: вы заметите, что в службе контактов я сделал:

//the Ajax call    
var metacontact = ContactDBServices.find({ID:contactID}, 
    function(){
        this.ID = contactID;
        this.firstName = metacontact.contact_name;
        this.lastName = metacontact.contact_last_name;
        this.phone = metacontact.contact_phone;
        this.fax = metacontact.contact_fax;
        this.mobile = metacontact.contact_mobile;
        this.email = metacontact.contact_email;
        this.web = metacontact.contact_web;

    },
    function(){
        contactPromise.reject("Error");
    }
);

ясно пишу this. в функции обратного вызова я не влиял на значения Контакта, но на атрибуты функции! Чтобы решить эту проблему, мне пришлось изменить обратный вызов следующим образом:

//the Ajax call    
var metacontact = ContactDBServices.find({ID:contactID}, 
    function(){
        self.ID = contactID;
        self.firstName = metacontact.contact_name;
        self.lastName = metacontact.contact_last_name;
        self.phone = metacontact.contact_phone;
        self.fax = metacontact.contact_fax;
        self.mobile = metacontact.contact_mobile;
        self.email = metacontact.contact_email;
        self.web = metacontact.contact_web;

    },
    function(){
        contactPromise.reject("Error");
    }
);

где

var self = this;

вне обратного вызова.

Другие вопросы по тегам