3

Some of my wording may be off especially regarding angular/js terminology (controller, service, factory, etc), but hopefully it is still understandable. Also, this question has multiple parts, which made it difficult to ask in one line.

I have 3 files: newRegistration.html, Registration.js, and addressVerification.js.

In newRegistration.html, there is a form where the user inputs his/her email, phone, mailing address, and other things and then clicks "next". Upon clicking next, Registration.js (a controller?) is triggered (?).

newRegistration.html

In the following snippet is the ng-repeat that I'd like to update with new data from addressVerification.js.

<div id="dialog-form" title="CHOOSE THE CORRECT ADDRESS">
    <ul>
        <li ng-repeat="for item in [not sure what to put here because of two js files]">

        </li>
    </ul>    
</div>

Registration.js

The controller for the template that contains the ng-repeat mentioned above.

The top line looks like this:

angular.module('appname')
    .controller('RegistrationCtrl', function ($scope, $http, cacheStore, countryStates, birthYear, $anchorScroll, errorMessages, addressVerification, UtilsFactory)

And this is a line that may be relevant:

addressVerification.verify(user).then(function (userObj) 

addressVerification.js

Uses the Smartystreets API to correct/suggest the mailing address.

I can't figure out how to pass variables from this module to Registration.js (where the scope variable [?] is) in order to populate the ng-repeat in newRegistration.html.

angular.module('appname').factory('addressVerification', function($q, userIdentity, $http,  smartyToken) {
    "use strict";

    return {
    verify: function(obj) {
        var deferred = $q.defer(),
        street2QS = "";

    if (obj.address2 || obj.address2 !== "") {
        street2QS = "&street2=" + encodeURIComponent(obj.address2);
    }

$http.jsonp("https://api.smartystreets.com/street-address?street=" + encodeURIComponent(obj.address1)
    + street2QS
    + "&city=" + encodeURIComponent(obj.city)
+ "&state=" + encodeURIComponent(obj.state)
+ "&zipcode=" + encodeURIComponent(obj.zip)
+ "&source=website&auth-token="+ smartyToken.get() + "&candidates=5&callback=JSON_CALLBACK")
.success(function (response) {
    var metaData,
    components;

        if (response && response.length === 1) {
        metaData = response[0].metadata || {};
        components = response[0].components || {};

            angular.extend(obj, {
        "address1": [
            components.primary_number,
        components.street_name,
        components.street_suffix
                    ].join(" "),
        "address2": [
        components.secondary_designator,
        components.secondary_number
        ].join(" "),
        "city": components.city_name,
        "county_name": metaData.county_name,
        "county_fips": metaData.county_fips,
        "state": components.state_abbreviation,
        "latitude": metaData.latitude,
        "longitude": metaData.longitude,
        "plus4_code": components.plus4_code,
        "zip": components.zipcode
        });
        deferred.resolve(obj);
        } else {
            deferred.reject(false);
        }
        }).error( function() {
            deferred.reject(false);
        });

        return deferred.promise;
    }
    };
});

I'm pretty clueless right now. I think I've given all of the necessary details. I wish I knew where to start. I read all about deferred objects, ng-repeat, and controllers, but it's confusing me.

Any help appreciated.

Walter Roman
  • 4,621
  • 2
  • 32
  • 36
Emil
  • 1,131
  • 13
  • 23

2 Answers2

1

You're injecting addressVerification into RegistrationCtrl. The value of addressVerification that is injected into the RegistrationCtrl is the value returned by executing the function you're defining here:

angular.module('appname')
.factory('addressVerification', function($q, userIdentity, $http, smartyToken)

Therefore you can access the stuff that's happening inside of the addressVerification.js file in the RegistrationCtrl.js file by adding methods to whatever it is you're returning in that function.

Once you have your data in RegistrationCtrl, you can access it from the view by appending data to the scope inside of RegistrationCtrl. Example:

This would go in RegistrationCtrl.js:

$scope.someItems = [1, 2, 3, 4];

This would go in the view:

<li ng-repeat="item in someItems">{{item}}</li>
patorjk
  • 2,164
  • 1
  • 20
  • 30
  • Thanks for the response. I have some confusion because the entire file (addressVerification.js) is wrapped in a return statement, and then there is a "return deferred.promise" statement at the end too. Does this sound familiar? – Emil Apr 20 '14 at 01:09
  • also, what do you mean adding methods to what I'm returning? – Emil Apr 20 '14 at 01:11
  • Can you post what addressVerification.js looks like? If it's returning an object (ie: return { ... }) then you can add methods to it and access those methods inside of your controller. – patorjk Apr 20 '14 at 01:20
  • edited the questions to include the entire addressVerification.js – Emil Apr 20 '14 at 01:29
  • So addressVerification is returning a JavaScript object with a verify property. You can add additional properties or refactor the object to use additional methods if you want to execute the code from inside the controller. – patorjk Apr 20 '14 at 01:49
1

The way that I have implemented this is by exposing methods of a factory that allow the controllers (and the controller's view(s)) that depend on it to store values within the same factory.

For example, in the following code, the setCurrent method of the customers factory stores a value, current in the factory. Because factories are singletons, will persist in the application. Even after the user's click on the <a> (in the following example) and they are taken to href="/", the value that was stored in customers.current will be accessible to the "/" route's controller if the same factory is a dependency for both controllers.

Template

<ul>
    <li>{{customers.current.name}}</li>
    <li 
        ng-repeat="customer in customers.all"
        >
        <a 
            class="action name"
            ng-click="customers.setCurrent(customer)"
            href="/"
            >
            {{customer.name}}
        </a>
    </li>
</ul>

Controller

angular
.module('CtrlCustomerList', [
    'CollectionCustomers',
])
.controller('CtrlCustomerList', function($scope, CollectionCustomers) {
    $scope.customers = CollectionCustomers;
});

Factory

angular
.module('CollectionCustomers', [
])
.factory("CollectionCustomers", function(Restangular, ModelCustomer, $location) {
    return {
        all     : [],
        current : null,
        setCurrent : function() {
            // Affect this.current
        }
    }
});
Walter Roman
  • 4,621
  • 2
  • 32
  • 36