Vuejs + typeahead this - undefined - javascript

I am trying to do a form with autocomplete. When a user type a part of a name typeahead suggests people that are in our database. If the user selects one of the suggestion I want to the full form to be filled from the autosuggestion.
Everything works but all my attempts to assign to the data object the value from the suggestion. When I log the this.newReviewer I get this is undefined... here is my code:
var Vue = require('vue')
var validator = require('vue-validator')
var resource = require('vue-resource')
Vue.use(validator)
Vue.use(resource)
var token = $('#token').attr('value');
Vue.http.headers.common['X-CSRF-TOKEN'] = token;
new Vue({
el:'#invite',
data: {
newReviewer: {
title:'',
last_name:'',
first_name:'',
email:'',
ers_id:'null'
},
reviewers: {},
quantity: {},
submitted: false,
},
ready: function(){
this.fetchInvitedReviewers();
console.log(this.newReviewer);
var ersContacts = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'api/search/%QUERY',
wildcard: '%QUERY'
}
});
$('#last_name')
.typeahead({
minLength: 2,
highlight: true,
hint: true
},
{
displayKey: 'last_name',
templates: {
suggestion: function(ersContacts) {
return (
'<div>' +
'<h3>'
+ ersContacts.title + ' '
+ ersContacts.first_name + ' '
+ ersContacts.last_name
+ '</h3>'
+ '<p class="uk-text-muted">'
+ ersContacts.city + ' '
+ ersContacts.country
+ '</p>' +
'</div>'
)
}
},
source: ersContacts
})
.on('typeahead:select', function(e, suggestion){
console.log(this.newReviewer);
this.newReviewer.last_name.push(suggestion.last_name);
this.newReviewer.email.push(suggestion.email);
})
.bind(this);
},
computed:{
//errors: function() {
// for(var key in this.newReviewer) {
// if (! this.newReviewer[key]) return true;
// }
// return false;
//}
},
methods: {
fetchInvitedReviewers: function() {
this.$http.get('api', function(response) {
this.$set('reviewers', response.reviewers);
this.$set('quantity', response.quantity);
});
},
onSubmitForm: function(e){
e.preventDefault();
var reviewer = this.newReviewer;
//add new reviewer to reviewers array
this.reviewers.push(reviewer);
//reset input values
this.newReviewer = {title:'', last_name: '', first_name: '', email:'', ers_id:''}
//substract one to the quantity
this.quantity -= 1 ;
//sent post ajax request
this.$http.post('api/store', reviewer)
//show success and count how many left
if(this.quantity <= 0) {
this.submitted = true;
}
}
},
validator: {
validates: {
email: function (val) {
return /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(val)
}
}
}
});

found...
Sorry guys. this
})
.bind(this);
should have been
}
.bind(this));

Related

Select2 group with Infinite scroll

I am using select2 group option with infinite scroll and data are coming by Ajax calling per page 10. Here is some problem arises, suppose user 1 has 15 data and user 2 has 15 data, at first 10 data are coming from user 1 and in next page 10 (5 data for user1 and 5 data for user2). no problem for data getting but the problem is user 1 group showing double. How can I prevent double display to my select2 options group? Has there any way to make an option group again?
HTML CODE
<div class="container">
<form id="frm">
<h1>Solution 1</h1>
<div class="row">
<div class="col-4">
<div class="form-group">
<label for="tagInput">Get data by ajax calling</label>
<select class="form-control" id="pictures_tag_input">
</select>
<small class="form-text text-muted"><p class="text-info">Infinite Scroll</p></small>
</div>
</div>
</div>
</form>
</div>
JS CODE
$(document).ready(function() {
// solution 1
//example.com/articles?page[number]=3&page[size]=1
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
// console.log(params.page || 1);
return {
q: params.term, // search term
_page: params.page || 1,
_limit: 10 // page size
};
},
processResults: function(data, params) {
params.page = params.page || 1;
var datx = getNestedChildren(data);
// console.log(datx);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
Demo
https://codepen.io/mdshohelrana/pen/MLVZEG
Just try to use the following code
templateResult: function(data) {
if (typeof data.children != 'undefined') {
$(".select2-results__group").each(function() {
if (data.text == $(this).text()) {
return data.text = '';
}
});
}
return data.text;
}
NOTE: Need to group from server side, Other wise you have to make master details from client side.
the accepted answer didn't work for me and I don't see why should that work. A return in the $.each will not return from the templateResult() function.
Here is an approach that worked for me.
It is not necessary to build a nested list by getNestedChildren(list) on javascript side. It is much easier to build it on server side instead.
The appearance of search results in the dropdown (options and the optgroups) can be customized by using the templateResult option. I removed the duplicated optgroups and labels by this option.
check the templateResult: formatOptions, part of the code
$(document).ready(function() {
$("#pictures_tag_input").select2({
placeholder: "Search for options",
templateResult: formatOptions,
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: true,
delay: 250,
minimumInputLength: 2,
data: function(params) {
return {
q: params.term,
_page: params.page || 1,
_limit: 10
};
},
processResults: function(data, params) {
params.page = params.page || 1;
return {
results: data,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function formatOptions(item, container, $el) {
// optgroups section
if (item.children && item.children.length > 0) {
// don't format the repeated optgroups!
if ($(".select2-results__group").text() === item.text) {
return;
}
if ($('[aria-label="' + item.text + '"]').length > 0) {
return;
}
// the first occasion of the given optgroup
return $el;
}
// options section
// here you can implement your own logic
// if you want to customise the output of the options
$el.addClass('something-special-result result');
return $el;
}
});
maybe the problem is a source of a data
You call user 1 .... server return a 1
You call user 2 .... server return a 1
You call user 3 .... server return a 2
You call user 4 .... server return a 2
You call user 5 .... server return a 3
You call user 6 .... server return a 3
curent_user = 1;
$(document).ready(function() {
http: $("#pictures_tag_input").select2({
placeholder: "Search for options",
ajax: {
url: "https://jsonplaceholder.typicode.com/users/1/todos",
dataType: "json",
global: false,
cache: false,
minimumInputLength: 2,
data: function(params) {
console.log("params",params || 1);
return {
q: params.term, // search term
_page: curent_user,
_limit: 10 // page size
};
},
processResults: function(data, params) {
curent_user += 2;
var datx = getNestedChildren(data);
console.log("data: ", data);
return {
results: datx,
pagination: {
more: true
}
};
} //end of process results
} // end of ajax
});
function getNestedChildren(list) {
var roots = [];
for (i = 0; i < list.length; i += 1) {
node = list[i];
if (roots.length === 0) {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
roots.push(obj);
} else {
var obj = {
text: "User " + node.userId,
children: [{ id: node.id, text: node.title }]
};
var rootArray = $.map(roots, function(val, i) {
var vl = "User " + node.userId;
if (val.text === vl) return val;
else return undefined;
});
if (rootArray.length > 0) {
var obj1 = {
id: node.id,
text: node.title
};
rootArray[0].children.push(obj1);
} else {
roots.push(obj);
}
}
}
return roots;
}
});
so if you skip a one step
You call user 1 .... server return a 1
You call user 3 .... server return a 2
You call user 5 .... server return a 3
I just found a better solution which does not result in a (duplicated) optgroup being rendered as an empty option:
processResults: function( json, params ){
setTimeout( function() {
var $prevOptions = false;
var $prevGroup = false;
// loop
$('.select2-results__option[role="group"]').each(function(){
// vars
var $options = $(this).children('ul');
var $group = $(this).children('strong');
// compare to previous
if( $prevGroup && $prevGroup.text() === $group.text() ) {
$prevOptions.append( $options.children() );
$(this).remove();
return;
}
// update vars
$prevOptions = $options;
$prevGroup = $group;
});
}, 1 );
return json;
}
Advanced Custom Fields uses the exact same code for their WordPress plugin in order to fix this issue, ajax-load and group posts from different post-types.

Integrating Braintree Client token into braintree.client.create

I have limited experience working with JavaScript and am attempting to pass a client token generated on my server into the braintree client create of Braintree's javascript code. I do not know how to pass the ClientToken out of the jQuery post and into the authorization section of braintree.client.create. A portion of my code is below:
<script src="https://js.braintreegateway.com/web/3.34.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.34.0/js/hosted-fields.min.js"></script>
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<script src="https://js.braintreegateway.com/web/3.34.0/js/paypal-checkout.min.js"></script>
<script>
var form = document.querySelector('#register-form');
var submit = document.querySelector('input[type="submit"]');
var ClientToken;
var authPosting = jQuery.post('/path/to/php_scripts/getClientToken.php');
authPosting.done(function( data ) {
ClientToken = data;
console.log(ClientToken);
});
braintree.client.create({
authorization: 'ClientToken'
}, function (clientErr, clientInstance) {
if (clientErr) {
console.error(clientErr);
return;
}
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'font-size': '15px',
'font-family': 'roboto, verdana, sans-serif',
'font-weight': 'lighter',
'color': 'black'
},
':focus': {
'color': 'black'
},
'.valid': {
'color': 'black'
},
'.invalid': {
'color': 'black'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: ''
},
cvv: {
selector: '#cvv',
placeholder: ''
},
expirationDate: {
selector: '#expiration-date',
placeholder: 'MM/YY'
},
postalCode: {
selector: '#postal-code',
placeholder: ''
}
}
}, function(err, hostedFieldsInstance) {
if (err) {
console.error(err);
return;
}
function findLabel(field) {
return jQuery('.hosted-field--label[for="' + field.container.id + '"]');
}
hostedFieldsInstance.on('focus', function (event) {
var field = event.fields[event.emittedBy];
findLabel(field).addClass('label-float').removeClass('filled');
jQuery(".error-msg").hide();
});
// Emulates floating label pattern
hostedFieldsInstance.on('blur', function (event) {
var field = event.fields[event.emittedBy];
var label = findLabel(field);
if (field.isEmpty) {
label.removeClass('label-float');
} else if (field.isValid) {
label.addClass('filled');
} else {
label.addClass('invalid');
}
});
hostedFieldsInstance.on('empty', function (event) {
var field = event.fields[event.emittedBy];
findLabel(field).removeClass('filled').removeClass('invalid');
});
hostedFieldsInstance.on('validityChange', function (event) {
var field = event.fields[event.emittedBy];
var label = findLabel(field);
if (field.isPotentiallyValid) {
label.removeClass('invalid');
} else {
label.addClass('invalid');
}
});
//Submit function
jQuery("#register-form").validate({
submitHandler: function(form) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (err, payload) {
if (err) {
if (err.code === 'HOSTED_FIELDS_FIELDS_EMPTY') {
var msg = "All credit card fields are required.";
jQuery(".error-msg").text(msg);
jQuery(".error-msg").show();
} else if (err.code === 'HOSTED_FIELDS_FIELDS_INVALID') {
var invalidFields = err.details.invalidFieldKeys;
invalidFields.forEach(function (field) {
if (field == "number") {
var myid = "card-number";
var myobj = "credit card number";
} else if (field == "expirationDate") {
var myid = "expiration-date";
var myobj = "expiration date";
}
jQuery("#" + myid).append("<div class='error-msg'>Please enter a valid " + myobj + ".</div>");
});
} else {
var msg = "There was an error on the form."
alert (msg);
}
return;
}
vfirst = jQuery( "input#firstname" ).val(),
vlast = jQuery( "input#lastname" ).val(),
vemail = jQuery( "input#email" ).val(),
vproof = jQuery( "input[name='proof']" ).val(),
vprice = jQuery( "tr#total td.price" ).data('price'),
vcourse = 1950,
vnonce = 'fake-valid-nonce',
url = '/path/to/php_scripts/placeOrder.php';
// This is where you would submit payload.nonce to your server
// alert('Submit your cc nonce to your server here!');
});
//form.submit();
}
});
});
....more code below....
</script>
Any suggestions would be greatly appreciated.
Answering my own question:
CLIENT_AUTHORIZATION = jQuery.parseJSON(jQuery.ajax({
url: "/path/to/php_scripts/TokenScript.php",
dataType: "json",
async: false
}).responseText);
braintree.client.create({
authorization: CLIENT_AUTHORIZATION.token
}, function (clientErr, clientInstance) {
if (clientErr) {
console.error(clientErr);
return;
} code continues.....
The CLIENT_AUTHORIZATION.token is whatever the token was named on the client authorization script.

Uninitialized constant Spree::Api::AramexAddressController::AramexAddressValidator

I am facing the following issue:
ActionController::RoutingError (uninitialized constant Spree::Api::AramexAddressController::AramexAddressValidator):
app/controllers/spree/api/aramex_address_controller.rb:2:in <class:AramexAddressController>
app/controllers/spree/api/aramex_address_controller.rb:1:in <top (required)>
I included the following in my controllers/spree/api/aramex_address_controller.rb:
class Spree::Api::AramexAddressController < ApplicationController
include AramexAddressValidator
# fetch cities from aramex api
def fetch_cities_from_aramex_address
response = []
zones = Spree::ShippingMethod.where(['LOWER(admin_name) like ?', '%aramex%']).map(&:zones).flatten
if zones.map(&:countries).flatten.map(&:iso).include?(params['country_code'])
response = JSON.parse(fetch_cities(params['country_code']))['Cities']
end
respond_to do |format|
format.json { render :json => response, :status => 200 }
end
end
# Validate address for aramex shipping
def validate_address_with_aramex
begin
zones = Spree::ShippingMethod.where(['LOWER(admin_name) like ?', '%aramex%']).map(&:zones).flatten
final_response = {}
if zones.map(&:countries).flatten.map(&:iso).include?(params[:b_country])
final_response[:b_errors] = confirm_address_validity(params[:b_city], params[:b_zipcode], params[:b_country])
end
if zones.map(&:countries).flatten.map(&:iso).include?(params[:s_country]) && params[:use_bill_address] == "false"
final_response[:s_errors] = confirm_address_validity(params[:s_city], params[:s_zipcode], params[:s_country])
end
rescue
return true
end
respond_to do |format|
format.json { render :json => final_response, :status => 200 }
end
end
# Confirm address validity with Aramex address validatio API
def confirm_address_validity(city, zipcode, country)
response = JSON.parse(validate_address(city, zipcode, country))
if response['HasErrors'] == true
if response['SuggestedAddresses'].present?
response['Notifications'].map{|data| data['Message']}.join(', ') + ', Suggested city name is - ' + response['SuggestedAddresses'].map{|data| data['City']}.join(', ')
else
if response['Notifications'].first['Code'] == 'ERR06'
response['Notifications'].map{|data| data['Message']}.join(', ')
else
cities_response = JSON.parse(fetch_cities(country, city[0..2]))
cities_response['Notifications'].map{|data| data['Message']}.join(', ') + ', Suggested city name is - ' + cities_response['Cities'].join(' ,')
end
end
end
end
end
In my route file I mentioned:
get 'validate_address_with_aramex', to: 'aramex_address#validate_address_with_aramex'
get 'fetch_cities_from_aramex_address', to: 'aramex_address#fetch_cities_from_aramex_address'
I included the following JS call for the submitted Aramex Ajax validation in assets/javascripts/spree/frontend/checkout/address.js:
Spree.ready(function($) {
Spree.onAddress = function() {
var call_aramex = true;
$("#checkout_form_address").on('submit', function(e) {
if ($('#checkout_form_address').valid()) {
var s_country = $("#order_ship_address_attributes_country_id").find('option:selected').attr('iso_code');
var s_zipcode = $("#order_ship_address_attributes_zipcode").val();
var s_city = $("#order_ship_address_attributes_city").val();
var b_country = $("#order_bill_address_attributes_country_id").find('option:selected').attr('iso_code');
var b_zipcode = $("#order_bill_address_attributes_zipcode").val();
var b_city = $("#order_bill_address_attributes_city").val();
if (call_aramex == true && (typeof aramex_countries !== 'undefined') && (aramex_countries.includes(b_country) || aramex_countries.includes(s_country))) {
e.preventDefault();
var error_id = $('#errorExplanation').is(':visible') ? '#errorExplanation' : '#manual_error'
$(error_id).html("").hide()
$.blockUI({
message: '<img src="/assets/ajax-loader.gif" />'
});
$.ajax({
url: "/api/validate_address_with_aramex",
type: 'GET',
dataType: "json",
data: {
s_country: s_country,
s_zipcode: s_zipcode,
s_city: s_city,
b_country: b_country,
b_zipcode: b_zipcode,
b_city: b_city,
use_bill_address: ($("#order_use_billing").is(":checked"))
},
success: function(result) {
$.unblockUI()
if (result.b_errors || result.s_errors) {
if (result.b_errors) {
$(error_id).append('<div>Billing Address ' + result.b_errors + ' </div>')
}
if (result.s_errors) {
$(error_id).append('<div>Shipping Address ' + result.s_errors + ' </div>')
}
if ((result.b_errors && !result.s_errors) && ($("#order_use_billing").is(":unchecked"))) {
$(".js-summary-edit").trigger("click")
}
$(error_id).show();
$('html, body').animate({
scrollTop: '0px'
}, 300);
} else {
call_aramex = false;
$('#checkout_form_address').submit()
}
},
error: function(xhr, status, error) {
$(error_id).append('Oops Something Went Wrong but you can process order')
$(error_id).show();
$.unblockUI()
$('html, body').animate({
scrollTop: '0px'
}, 300);
$('#checkout_form_address').submit()
}
});
}
}
})
var getCountryId, order_use_billing, update_shipping_form_state;
if (($('#checkout_form_address')).is('*')) {
($('#checkout_form_address')).validate({
rules: {
"order[bill_address_attributes][city]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 22)
}
},
"order[bill_address_attributes][firstname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 15)
}
},
"order[bill_address_attributes][lastname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 17)
}
},
"order[bill_address_attributes][address1]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 32)
}
},
"order[bill_address_attributes][address2]": {
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 32)
}
},
"order[bill_address_attributes][zipcode]": {
maxlength: function(element) {
return maxCharLimit($("#order_bill_address_attributes_country_id").val(), 10)
}
},
"order[ship_address_attributes][city]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 22)
}
},
"order[ship_address_attributes][firstname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 15)
}
},
"order[ship_address_attributes][lastname]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 17)
}
},
"order[ship_address_attributes][address1]": {
required: true,
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 32)
}
},
"order[ship_address_attributes][address2]": {
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 32)
}
},
"order[ship_address_attributes][zipcode]": {
maxlength: function(element) {
return maxCharLimit($("#order_ship_address_attributes_country_id").val(), 10)
}
}
}
});
getCountryId = function(region) {
return $('#' + region + 'country select').val();
};
isCountryUsOrCa = function(country_id) {
return ["38", "232"].includes(country_id)
}
maxCharLimit = function(country_id, limit) {
if (["38", "232"].includes(country_id)) {
return limit;
} else {
return 255;
}
};
Spree.updateState = function(region) {
var countryId;
var cityId
countryId = getCountryId(region);
if (countryId != null) {
if (region == 'b') {
cityId = '#order_bill_address_attributes_city'
countryInputId = "#order_bill_address_attributes_country_id"
} else {
cityId = '#order_ship_address_attributes_city'
countryInputId = "#order_ship_address_attributes_country_id"
}
fill_cities($(countryInputId).find('option:selected').attr('iso_code'), cityId)
if (Spree.Checkout[countryId] == null) {
return $.get(Spree.routes.states_search, {
country_id: countryId
}, function(data) {
Spree.Checkout[countryId] = {
states: data.states,
states_required: data.states_required
};
return Spree.fillStates(Spree.Checkout[countryId], region);
});
} else {
return Spree.fillStates(Spree.Checkout[countryId], region);
}
}
};
fill_cities = function(country_code, cityId) {
$.ajax({
url: "/api/fetch_cities_from_aramex_address",
type: 'GET',
dataType: "json",
data: {
country_code: country_code
},
success: function(data) {
$(cityId).autocomplete({
source: data,
});
},
error: function() {}
});
}
Spree.fillStates = function(data, region) {
var selected, stateInput, statePara, stateSelect, stateSpanRequired, states, statesRequired, statesWithBlank;
statesRequired = data.states_required;
states = data.states;
statePara = $('#' + region + 'state');
stateSelect = statePara.find('select');
stateInput = statePara.find('input');
stateSpanRequired = statePara.find('[id$="state-required"]');
if (states.length > 0) {
selected = parseInt(stateSelect.val());
stateSelect.html('');
statesWithBlank = [{
name: '',
id: ''
}].concat(states);
$.each(statesWithBlank, function(idx, state) {
var opt;
opt = ($(document.createElement('option'))).attr('value', state.id).html(state.name);
if (selected === state.id) {
opt.prop('selected', true);
}
return stateSelect.append(opt);
});
stateSelect.prop('disabled', false).show();
stateInput.hide().prop('disabled', true);
statePara.show();
stateSpanRequired.show();
if (statesRequired) {
stateSelect.addClass('required');
}
stateSelect.removeClass('hidden');
return stateInput.removeClass('required');
} else {
stateSelect.hide().prop('disabled', true);
stateInput.show();
if (statesRequired) {
stateSpanRequired.show();
stateInput.addClass('required');
} else {
stateInput.val('');
stateSpanRequired.hide();
stateInput.removeClass('required');
}
statePara.toggle(!!statesRequired);
stateInput.prop('disabled', !statesRequired);
stateInput.removeClass('hidden');
return stateSelect.removeClass('required');
}
};
($('#bcountry select')).change(function() {
$('label.error').hide()
if (isCountryUsOrCa($("#order_bill_address_attributes_country_id").val())) {
$('#checkout_form_address').valid();
}
return Spree.updateState('b');
});
($('#scountry select')).change(function() {
$('label.error').hide()
if (isCountryUsOrCa($("#order_bill_address_attributes_country_id").val())) {
$('#checkout_form_address').valid();
}
return Spree.updateState('s');
});
Spree.updateState('b');
order_use_billing = $('input#order_use_billing');
order_use_billing.change(function() {
return update_shipping_form_state(order_use_billing);
});
update_shipping_form_state = function(order_use_billing) {
if (order_use_billing.is(':checked')) {
($('#shipping .inner')).hide();
return ($('#shipping .inner input, #shipping .inner select')).prop('disabled', true);
} else {
($('#shipping .inner')).show();
($('#shipping .inner input, #shipping .inner select')).prop('disabled', false);
return Spree.updateState('s');
}
};
return update_shipping_form_state(order_use_billing);
}
};
return Spree.onAddress();
});
Why am I am facing the issue mentioned at the top?
maybe you can try this:
namespace :spree do
namespace :api do
resources :aramex_address, only: [] do
get :validate_address_with_aramex
get :fetch_cities_from_aramex_address
end
end
end
words of advice I think it's better if you rename the fetch_cities_from_aramex_address with show method, so it still follow rails convenience
well here is the issue of constant lookup. Your constant that is AramexAddressValidator is missing because of the way you wrote class Spree::Api::AramexAddressController < ApplicationController
So if your module AramexAddressValidator is inside some scope use that scope also while including this module
For Ex. if its inside spree/aramex_address_validator use
include Spree::AramexAddressValidator

Determine when dojo dijit dialog and all widgets have completed first load/populate

Ok, I have what may be seem like a very dumb question to many of you, but I'm stumped. I'm working on a somewhat dated dojo project. Part of it has been converted to AMD and part hasn't. This part hasn't, so please bear with me.
I have a page that loads with a dgrid and has the shell of a dijit.Dialog built but hidden in html markup. There is a edit button on the page that when pressed, builds and populates the dialog and it's associated dijits (Selects, multiselects, etc. via old dojox.data.XmlStores and uses the data from the selected grid row to select the correct data in each dijit. As the dijits are built, onChange events are added. when the data is set in these dijits, the onChange events fire. This is needed. Sometimes one dijit's value needs to change another dijit's value...even on the first load. However, I have a couple extra javascript funtions that are tied to onChange events and set values of fields based on other values on the page. These DO NOT need to run on the first full load of the dialog and all its fields.
Here's what I think are the relevant pieces of my code:
The HTML markup:
<div class="dijitHidden">
<div data-dojo-type="dijit.Dialog" style="width:800px;text-align:left;" id="editDialog">
<table width='800px' cellpadding='25px' cellspacing='10px'>
<tr>
<td align="right"><From: </td>
<td align="left">
<div id="fromSelector"></div>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td align="right">Unit: </td>
<td align="left">
<div id="fromUnitSelector"></div>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td align="right">Room: </td>
<td align="left">
<div id="fromRoomSelector"></div>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td align="right">Mode: </td>
<td align="left" id="mode">
<div id="modeSelector"></div>
</td>
<td align="right">Priority:</td>
<td align="left" id="priority">
<div id="prioritySelector"></div>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td align="right">Transporters: </td>
<td align="left" id="numSel">
<div id="numTranSelector"></div>
</td>
</tr>
<tr>
<td align="right">Type: </td>
<td align="left" id="type">
<div id="typeSelector"></div>
</td>
<td align="right">Comments:</td>
<td align="left" id="comment">
<div id="comments"></div>
</td>
</tr>
</table>
</div>
</div>
Javascript:
function edit_button_pressed() {
//Javascript that creates the boxes
//begin From Location
dojo.byId("fromSelector").innerHTML = "";
var fromSelector = dojo.byId("fromSelector");
var locStore = new dojox.data.XmlStore({
url: 'getlocations.url',
label: 'label',
keyAttribute:'id'
});
function sizeLocs(size, request){
var requests = size;
if (requests > 0) {
//from
var fromSelect = new dijit.form.Select({
name: "fromSelect",
id: "fromSelect",
store: locStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(fromSelector);
fromSelect.startup();
fromSelect.addOption({label: '--Select a Loc--', value: ' '});
if (transFromLoc.length > 0) {
fromSelect.set('value', transFromLoc);
} else {
fromSelect.set('value', ' ');
}
if (disableBecauseStarted) {
fromSelect.set('disabled', 'disabled');
}
fromSelect.on("change", function(){
if ((String(fromSelect.value) != String(defaultOrigination)) || disableBecauseStarted) {
dijit.byId('fromUnitSelect').set('disabled', 'disabled');
dijit.byId('fromRoomSelect').set('disabled', 'disabled');
} else {
dijit.byId('fromUnitSelect').set('disabled', false);
dijit.byId('fromRoomSelect').set('disabled', false);
}
setAutoPriority();
})
}
}
//end from location
//Units Select
var unitStore = new dojox.data.XmlStore({
url: 'getUnits.url',
label: 'label',
keyAttribute:'id'
});
//from
var fromUnitSelect = new dijit.form.Select({
name: "fromUnitSelect",
id: "fromUnitSelect",
store: unitStore,
style: "width: 150px;",
labelAttr: "label"
}).placeAt(dojo.byId('fromUnitSelector'));
fromUnitSelect.startup();
fromUnitSelect.set('disabled', 'disabled');
fromUnitSelect.addOption({label: '--Unit--', value: ' '});
if (transFromUnit.length > 0) {
fromUnitSelect.set('value', transFromUnit);
} else {
fromUnitSelect.set('value', ' ');
}
fromUnitSelect.on("change", function(){
dijit.byId('fromRoomSelect').destroy();
var fromRoomStore = new dojox.data.XmlStore({
url: 'getRooms.url?UNIT=' + this.value,
label: 'label',
keyAttribute:'id'
});
var fromRoomSelect = new dijit.form.Select({
name: "fromRoomSelect",
id: "fromRoomSelect",
store: fromRoomStore,
style: "width: 150px;",
labelAttr: "label"
}).placeAt(dojo.byId('fromRoomSelector'));
fromRoomSelect.startup();
fromRoomSelect.addOption({label: '--Select a Room--', value: ' '});
if (transFromRoom.length > 0) {
fromRoomSelect.set('value', transFromRoom);
} else {
fromRoomSelect.set('value', ' ');
}
if (String(dijit.byId('fromSelect').value) != String(defaultOrigination)) {
dijit.byId('fromUnitSelect').set('disabled', 'disabled');
dijit.byId('fromRoomSelect').set('disabled', 'disabled');
} else {
dijit.byId('fromUnitSelect').set('disabled', false);
dijit.byId('fromRoomSelect').set('disabled', false);
}
if (dijit.byId('patientSelect') != null
&& String(dijit.byId('patientSelect').value).length > 1 ) {
var patientDataStore = new dojox.data.XmlStore({
url: 'getPatient.url?MRN=' + String(dijit.byId('patientSelect').value),
rootItem: "patient"
});
var getPat = function(items, request){
for(var i = 0; i < items.length; i++){
var item = items[i];
var assignedRoom = String(patientDataStore.getValue(item, "assignedRoom"));
var reservationRoom = String(patientDataStore.getValue(item, "roomReservationRoom"));
}
if (reservationRoom.length > 0 ) {
setAssToRoom(reservationRoom);
setAssRoom(assignedRoom);
} else {
setAssToRoom(assignedRoom);
setAssRoom(assignedRoom);
}
}
var request = patientDataStore.fetch({query:{}, onComplete: getPat});
}
setAutoPriority();
})
//Begin Modes
dojo.byId("createModeSelector").innerHTML = "";
var createModeSelector = dojo.byId("createModeSelector");
var transModeStore = new dojox.data.XmlStore({
url: '/workassign/getTransModes.wa',
label: 'label',
keyAttribute:'id'
});
function transSizeMode(size, request){
var requests = size;
var modeSelect = "";
if (requests > 0) {
createModeSelect = new dijit.form.Select({
name: "createModeSelect",
id: "createModeSelect",
store: transModeStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(createModeSelector);
createModeSelect.startup();
createModeSelect.addOption({label: '--Select a Mode--', value: ' '});
}
}
transModeStore.fetch({query: {}, onBegin: transSizeMode, start: 0, count: 0});
//End Modes
//Begin Types
dojo.byId("typeSelector").innerHTML = "";
var typeSelector = dojo.byId("typeSelector");
var transTypeStore = new dojox.data.XmlStore({
url: 'getType.url',
label: 'label',
keyAttribute:'id'
});
var typeSel = new dijit.form.MultiSelect({
name: 'typeSelect',
id: 'typeSelect',
style: 'width: 200px; font-size: 18px;'
}).placeAt(typeSelector);
var fillTypes = function(items, request){
dojo.forEach(items, function(item) {
var c = dojo.doc.createElement('option');
c.innerHTML = transTypeStore.getValue(item, "label");
c.value = transTypeStore.getValue(item, "id");
typeSelect.appendChild(c);
})
if (transType.length > 0) {
var transArray = transType.split(",");
typeSel.set('value', transArray);
} else {
typeSel.set("value", " ");
}
}
typeSel.on("change", function(){
setAutoPriority();
setAutoTransporters();
})
typeSel.startup();
//End Types
dojo.byId("prioritySelector").innerHTML = "";
var prioritySelector = dojo.byId("prioritySelector");
var priorityModeStore = new dojox.data.XmlStore({
url: 'getPriorities.url',
label: 'label',
keyAttribute:'id'
});
function prioritySizeMode(size, request){
var requests = size;
var modeSelect = "";
if (requests > 0) {
prioritySelect = new dijit.form.Select({
name: "prioritySelect",
id: "prioritySelect",
store: priorityModeStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(prioritySelector);
prioritySelect.startup();
prioritySelect.addOption({label: '--Select a Priority--', value: ' '});
}
if (priorityType.length > 0) {
prioritySelect.set('value', priorityType);
} else {
prioritySelect.set('value', ' ');
}
if(userLevel=="TransScheduler") {
//Check priority override property
dojo.request.xhr("/workassign/getPriorityOverrideStatus.wa", {
handleAs: "text"
}).then(function(data){
if (data.indexOf("false") > -1) {
dijit.byId('prioritySelect').set('disabled',true);
}
}, function(err){
// Handle the error condition
alert("error: " + err);
}, function(evt){
// Handle a progress event from the request if the
// browser supports XHR2
});
}
}
//Fetches and populate data
transModeStore.fetch({query: {}, onBegin: transSizeMode, start: 0, count: 0});
transTypeStore.fetch({query: {}, onComplete: fillTypes});
priorityModeStore.fetch({query: {}, onBegin: prioritySizeMode, start: 0, count: 0});
locStore.fetch({query: {}, onBegin: sizeLocs, start: 0, count: 0});
//show the dialog
dijit.byId("editDialog").show();
} //end edit_button_pressed
function setAutoPriority() {
var params = "";
if (dijit.byId("fromUnitSelect")) {
params = params + "&FROMUNIT=" + dijit.byId("fromUnitSelect").get("value");
}
if (dijit.byId("toUnitSelect")) {
params = params + "&TOUNIT=" + dijit.byId("toUnitSelect").get("value");
}
if (dijit.byId("fromSelect")) {
params = params + "&FROMLOCATION=" + dijit.byId("fromSelect").get("value");
}
if (dijit.byId("toSelect")) {
params = params + "&TOLOCATION=" + dijit.byId("toSelect").get("value");
}
if (dijit.byId("typeSelect")) {
params = params + "&TYPE=" + dijit.byId("typeSelect").get("value");
}
dojo.request.xhr("getHighestPriority.URL?NUM=0" + params, {
handleAs: "text"
}).then(function(data){
if (dijit.byId("prioritySelect")) {
dijit.byId("prioritySelect").set('value', data);
}
}, function(err){
// Handle the error condition
alert("error: " + err);
}, function(evt){
// Handle a progress event from the request if the
// browser supports XHR2
});
}
function setAutoTransporters() {
var params = "";
if (dijit.byId("typeSelect")) {
params = params + "TYPES=" + dijit.byId("typeSelect").get("value");
}
dojo.request.xhr("getHighestNum.url?" + params, {
handleAs: "text"
}).then(function(data){
if (dijit.byId("numTransSelect")) {
dijit.byId("numTransSelect").set('value', data);
}
}, function(err){
// Handle the error condition
alert("error: " + err);
}, function(evt){
// Handle a progress event from the request if the
// browser supports XHR2
});
}
As you can see I have fetches that call the XmlStores and select what should be selected in the individual dijits when applicable. The problem functions for me are the setAutoPriority() and setAutoTransporters(). I could easily pass a variable to those functions to tell it whether or not it was the first load...or even wrap their call in an if statement. I just can't figure out how to tell that everything (populating the dijits with data and set their value) has happened.
Any ideas would be appreciated. Nothing I've come up with has worked so far. And just FYI, depending on the data from the grid row selected, not every one of those dijits will change/have data selected every time...which muddies the water even more.
So,
this is just a draft idea:
i cannot test it
it is dirty (there are better ways of doing)
But the general idea is there.
Core part of the idea are the first 4 lines of code.
var fetchDone = 0;
function isReady() {
return fetchDone >= 4; //the amount of fetch you have bellow
}
function edit_button_pressed() {
//Javascript that creates the boxes
//begin From Location
//reset the counter
fetchDone = 0;
dojo.byId("fromSelector").innerHTML = "";
var fromSelector = dojo.byId("fromSelector");
var locStore = new dojox.data.XmlStore({
url: 'getlocations.url',
label: 'label',
keyAttribute: 'id'
});
function sizeLocs(size, request) {
var requests = size;
if (requests > 0) {
//from
var fromSelect = new dijit.form.Select({
name: "fromSelect",
id: "fromSelect",
store: locStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(fromSelector);
fromSelect.startup();
fromSelect.addOption({
label: '--Select a Loc--',
value: ' '
});
if (transFromLoc.length > 0) {
fromSelect.set('value', transFromLoc);
} else {
fromSelect.set('value', ' ');
}
if (disableBecauseStarted) {
fromSelect.set('disabled', 'disabled');
}
fromSelect.on("change", function() {
if ((String(fromSelect.value) != String(defaultOrigination)) || disableBecauseStarted) {
dijit.byId('fromUnitSelect').set('disabled', 'disabled');
dijit.byId('fromRoomSelect').set('disabled', 'disabled');
} else {
dijit.byId('fromUnitSelect').set('disabled', false);
dijit.byId('fromRoomSelect').set('disabled', false);
}
setAutoPriority();
})
}
}
//end from location
//Units Select
var unitStore = new dojox.data.XmlStore({
url: 'getUnits.url',
label: 'label',
keyAttribute: 'id'
});
//from
var fromUnitSelect = new dijit.form.Select({
name: "fromUnitSelect",
id: "fromUnitSelect",
store: unitStore,
style: "width: 150px;",
labelAttr: "label"
}).placeAt(dojo.byId('fromUnitSelector'));
fromUnitSelect.startup();
fromUnitSelect.set('disabled', 'disabled');
fromUnitSelect.addOption({
label: '--Unit--',
value: ' '
});
if (transFromUnit.length > 0) {
fromUnitSelect.set('value', transFromUnit);
} else {
fromUnitSelect.set('value', ' ');
}
fromUnitSelect.on("change", function() {
dijit.byId('fromRoomSelect').destroy();
var fromRoomStore = new dojox.data.XmlStore({
url: 'getRooms.url?UNIT=' + this.value,
label: 'label',
keyAttribute: 'id'
});
var fromRoomSelect = new dijit.form.Select({
name: "fromRoomSelect",
id: "fromRoomSelect",
store: fromRoomStore,
style: "width: 150px;",
labelAttr: "label"
}).placeAt(dojo.byId('fromRoomSelector'));
fromRoomSelect.startup();
fromRoomSelect.addOption({
label: '--Select a Room--',
value: ' '
});
if (transFromRoom.length > 0) {
fromRoomSelect.set('value', transFromRoom);
} else {
fromRoomSelect.set('value', ' ');
}
if (String(dijit.byId('fromSelect').value) != String(defaultOrigination)) {
dijit.byId('fromUnitSelect').set('disabled', 'disabled');
dijit.byId('fromRoomSelect').set('disabled', 'disabled');
} else {
dijit.byId('fromUnitSelect').set('disabled', false);
dijit.byId('fromRoomSelect').set('disabled', false);
}
if (dijit.byId('patientSelect') != null && String(dijit.byId('patientSelect').value).length > 1) {
var patientDataStore = new dojox.data.XmlStore({
url: 'getPatient.url?MRN=' + String(dijit.byId('patientSelect').value),
rootItem: "patient"
});
var getPat = function(items, request) {
for (var i = 0; i < items.length; i++) {
var item = items[i];
var assignedRoom = String(patientDataStore.getValue(item, "assignedRoom"));
var reservationRoom = String(patientDataStore.getValue(item, "roomReservationRoom"));
}
if (reservationRoom.length > 0) {
setAssToRoom(reservationRoom);
setAssRoom(assignedRoom);
} else {
setAssToRoom(assignedRoom);
setAssRoom(assignedRoom);
}
}
var request = patientDataStore.fetch({
query: {},
onComplete: getPat
});
}
setAutoPriority();
})
//Begin Modes
dojo.byId("createModeSelector").innerHTML = "";
var createModeSelector = dojo.byId("createModeSelector");
var transModeStore = new dojox.data.XmlStore({
url: '/workassign/getTransModes.wa',
label: 'label',
keyAttribute: 'id'
});
function transSizeMode(size, request) {
var requests = size;
var modeSelect = "";
if (requests > 0) {
createModeSelect = new dijit.form.Select({
name: "createModeSelect",
id: "createModeSelect",
store: transModeStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(createModeSelector);
createModeSelect.startup();
createModeSelect.addOption({
label: '--Select a Mode--',
value: ' '
});
}
}
transModeStore.fetch({
query: {},
onBegin: transSizeMode,
start: 0,
count: 0
});
//End Modes
//Begin Types
dojo.byId("typeSelector").innerHTML = "";
var typeSelector = dojo.byId("typeSelector");
var transTypeStore = new dojox.data.XmlStore({
url: 'getType.url',
label: 'label',
keyAttribute: 'id'
});
var typeSel = new dijit.form.MultiSelect({
name: 'typeSelect',
id: 'typeSelect',
style: 'width: 200px; font-size: 18px;'
}).placeAt(typeSelector);
var fillTypes = function(items, request) {
dojo.forEach(items, function(item) {
var c = dojo.doc.createElement('option');
c.innerHTML = transTypeStore.getValue(item, "label");
c.value = transTypeStore.getValue(item, "id");
typeSelect.appendChild(c);
})
if (transType.length > 0) {
var transArray = transType.split(",");
typeSel.set('value', transArray);
} else {
typeSel.set("value", " ");
}
}
typeSel.on("change", function() {
setAutoPriority();
setAutoTransporters();
})
typeSel.startup();
//End Types
dojo.byId("prioritySelector").innerHTML = "";
var prioritySelector = dojo.byId("prioritySelector");
var priorityModeStore = new dojox.data.XmlStore({
url: 'getPriorities.url',
label: 'label',
keyAttribute: 'id'
});
function prioritySizeMode(size, request) {
var requests = size;
var modeSelect = "";
if (requests > 0) {
prioritySelect = new dijit.form.Select({
name: "prioritySelect",
id: "prioritySelect",
store: priorityModeStore,
style: "width: 200px;",
labelAttr: "label"
}).placeAt(prioritySelector);
prioritySelect.startup();
prioritySelect.addOption({
label: '--Select a Priority--',
value: ' '
});
}
if (priorityType.length > 0) {
prioritySelect.set('value', priorityType);
} else {
prioritySelect.set('value', ' ');
}
if (userLevel == "TransScheduler") {
//Check priority override property
dojo.request.xhr("/workassign/getPriorityOverrideStatus.wa", {
handleAs: "text"
}).then(function(data) {
if (data.indexOf("false") > -1) {
dijit.byId('prioritySelect').set('disabled', true);
}
}, function(err) {
// Handle the error condition
alert("error: " + err);
}, function(evt) {
// Handle a progress event from the request if the
// browser supports XHR2
});
}
}
var onFetchComplete = function() {
fetchDone++;
};
//Fetches and populate data
transModeStore.fetch({
query: {},
onBegin: transSizeMode,
onComplete: onFetchComplete,
start: 0,
count: 0
});
transTypeStore.fetch({
query: {},
onComplete: function() {
onFetchComplete();
fillTypes.apply(this, arguments);
}
});
priorityModeStore.fetch({
query: {},
onBegin: prioritySizeMode,
onComplete: onFetchComplete,
start: 0,
count: 0
});
locStore.fetch({
query: {},
onBegin: sizeLocs,
onComplete: onFetchComplete,
start: 0,
count: 0
});
//show the dialog
dijit.byId("editDialog").show();
} //end edit_button_pressed
function setAutoPriority() {
if (!isReady()) {
return;
}
var params = "";
if (dijit.byId("fromUnitSelect")) {
params = params + "&FROMUNIT=" + dijit.byId("fromUnitSelect").get("value");
}
if (dijit.byId("toUnitSelect")) {
params = params + "&TOUNIT=" + dijit.byId("toUnitSelect").get("value");
}
if (dijit.byId("fromSelect")) {
params = params + "&FROMLOCATION=" + dijit.byId("fromSelect").get("value");
}
if (dijit.byId("toSelect")) {
params = params + "&TOLOCATION=" + dijit.byId("toSelect").get("value");
}
if (dijit.byId("typeSelect")) {
params = params + "&TYPE=" + dijit.byId("typeSelect").get("value");
}
dojo.request.xhr("getHighestPriority.URL?NUM=0" + params, {
handleAs: "text"
}).then(function(data) {
if (dijit.byId("prioritySelect")) {
dijit.byId("prioritySelect").set('value', data);
}
}, function(err) {
// Handle the error condition
alert("error: " + err);
}, function(evt) {
// Handle a progress event from the request if the
// browser supports XHR2
});
}
function setAutoTransporters() {
if (!isReady()) {
return;
}
var params = "";
if (dijit.byId("typeSelect")) {
params = params + "TYPES=" + dijit.byId("typeSelect").get("value");
}
dojo.request.xhr("getHighestNum.url?" + params, {
handleAs: "text"
}).then(function(data) {
if (dijit.byId("numTransSelect")) {
dijit.byId("numTransSelect").set('value', data);
}
}, function(err) {
// Handle the error condition
alert("error: " + err);
}, function(evt) {
// Handle a progress event from the request if the
// browser supports XHR2
});
}

Typeahead.js Suggest Not Rendering Properly

I am using the Typeahead.js plugin. I am trying to create custom templates for the suggestions. Currently, I have the following:
var suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: '/api/suggests?querytext=%QUERY'
});
suggestions.initialize();
$(document).ready(function() {
$('input.typeahead').typeahead(
{ minLength: 3 },
{
name: 'suggestions',
source: suggestions.ttAdapter(),
templates: {
suggestion: function(data) {
var str = '';
str += '<div>Result: ';
// if suggestion is a Customer show 1 icon and the Name
// elseif suggestion is a Product show a different icon and the name
str += '</div>';
return str;
}
}
}
);
});
The suggestions are popping up. However, I am unable to actually get the property values from inside of my results. When Bloodhound requests the suggestions, I get a result set back that looks like this:
{
"Results":[
{
"Type":"Customer",
"Id":5,
"Name":"Bill",
"LastUpdated":"01-01-2015"
},
{
"Type":"Customer",
"Id":135,
"Name":"Billows",
"LastUpdated":"01-02-2015",
},
{
"Type":"Product",
"Id":241,
"Name":"Bill Check",
"LastUpdate":"01-04-2015"
}
],
"TotalResults":3,
"TotalCustomers":2,
"TotalProducts":1
}
How do I get the individual Name and Type values for a single suggestion in the template so I can render it properly?
Thank you!
Try this
var suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: '/api/suggests?querytext=%QUERY',
filter: function(list) {
var suggestions = list.Results;
return $.map(suggestions, function(suggestion) { return { Type: suggestion.Type, Id: suggestion.Id, Name: suggestion.Name, LastUpdated: suggestion.LastUpdated }; });
}
}
});
suggestions.initialize();
$(document).ready(function () {
$('input.typeahead').typeahead(
{ minLength: 3 },
{
name: 'suggestions',
source: suggestions.ttAdapter(),
templates: {
suggestion: function (data) {
var str = '';
str += '<div>Result: ';
// get value by data.Type data.Name
str += '</div>';
return str;
}
}
}
);
});

Categories

Resources