Fazendo um elemento personalizado simples no angularjs

Ao converter um aplicativo Rails para Angularjs. Eu encontrei uma entrada selecionada que carregou alguns nomes de estados dos EUA de um arquivo yaml.

.control-container= state_selector form, :"#{type}state", {}, :validate => validate, :class => %w(control--full-line)

Esses estados vêm de um arquivo yaml indiretamente

def state_selector(form, field_name, options={ }, html_options={ })
states
= [['', '']]
states
+= Countries.us_states.sort.map { |us_state_code, _| [us_state_code, us_state_code] }
form
.select field_name, states, options, html_options
end

Converti o yaml em json e o incorporei em um controlador angular para este formulário. Aqui está a primeira passagem em uma conversão para angular de um auxiliar de trilhos.

 <label class="above-field" for="state">State</label>
<select class="field" name="state" ng-model="payment.state" ng-options="state.abbreviation as state.name for state in states" required>
$scope.states = function(rawStates) { 
return _.map(rawStates, function(abbreviation, name) {
return {abbreviation: abbreviation, name: name};
});
}({
"CA": "CALIFORNIA",
// the rest of the states
"NY": "NEW YORK"
});

É entediante incorporar a cada página em que possa precisar de uma lista de estados. A maneira mais rápida de contornar isso é extrair os estados em um provedor de valor.

angular.module('canHazApp')
.value('states',
function(rawStates) {
return _.map(rawStates, function(abbreviation, name) {
return {abbreviation: abbreviation, name: name};
});
}({
"AK": "ALASKA",
// the rest of the states
"WY": "WYOMING"
}));

em seguida, em app / scripts / controllers / contact_form.js

angular.module('canHazApp')
.controller('ContactFormCtrl', function($scope, states) { //inject the value
//lots of code
$scope
.states = states
});

Agora temos isso para que nossos estados não sejam duplicados se decidirmos extrair estados em outro controle em outro lugar. No entanto, teríamos que adicionar statesdependências de cada controlador que precisa da lista de estados.

Podemos extrair isso mais para uma diretiva, de modo que não tenhamos que definir estados no escopo do elemento select. Removemos os estados de contact_form.js e movemos a dependência para uma diretiva.

angular.module('canHazApp')
.directive('stateOptions', function (states) { //states value injected into directive context
return {
restrict: 'E',
replace
: true,
scope
: true, //we want a separate child scope
template
: '<select ng-options="state.abbreviation as state.name for state in states"></select>',
require
: '^ngModel',
link
: function(scope, element, attrs) {
scope
.states = states;
}
};
});

agora podemos usar nossa diretiva em qualquer lugar do aplicativo e obter nossa lista de estados como opções para selecionar.

<label class="above-field" for="state">State</label>
<state-options class="field" name="state" ng-model="payment.state" required></state-options>