I'm using EasyAutocomplete to select some data.
The problem I'm having is that I only can use one autocomplete input. I tried to find a solution but I didn't find anything in the documentation.
My code:
<%= form_tag('/search', local: true, method: :get, class: 'form-group row' ) do %>
<div class="col-md-5">
<%= text_field_tag(:q, nil, data: { behavior: 'autocomplete-lang' }, placeholder: 'Lenguaje', class: 'form-control') %>
</div>
<% end %>
<%= form_tag('/search', local: true, method: :get, class: 'form-group row' ) do %>
<div class="col-md-5">
<%= text_field_tag(:q, nil, data: { behavior: 'autocomplete-ide' }, placeholder: 'Lenguaje', class: 'form-control') %>
</div>
<% end %>
Controller:
def search
#lang = Content.ransack(name_cont: params[:q],types_id_eq: 1).result(distinct: true)
#ide = Content.ransack(name_cont: params[:q],types_id_eq: 4).result(distinct: true)
respond_to do |format|
format.html {}
format.json {
#lang = #lang.limit(5)
#ide = #ide.limit(5)
}
end
end
Js:
document.addEventListener("turbolinks:load", function() {
var $input = $("[data-behavior='autocomplete-lang']");
var options = {
getValue: "name",
url : function(phrase) {
return "/search.json?q=" + phrase;
},
categories: [
{
listLocation: "lang"
}
],
list: {
onChooseEvent: function () {
var id = $input.getSelectedItemData().id;
console.log(id);
}
}
};
$input.easyAutocomplete(options);
});
document.addEventListener("turbolinks:load", function() {
var $input_ide = $("[data-behavior='autocomplete-ide']");
//IDE
var options_ide = {
getValue: "name",
url : function(phrase) {
return "/search.json?q=" + phrase;
},
categories: [
{
listLocation: "ide"
}
],
list: {
onChooseEvent: function () {
var id = $input_ide.getSelectedItemData().id;
console.log(id);
}
}
};
$input_ide.easyAutocomplete(options_ide);
});
So, I only can use once the easyAutocomplete, if I use it twice the behavior is not correct and only one input work.
I really need a hand to solve this, is must be pretty simple, but I can't get it.
I faced the same problem and solved it by adding unique "id"s to each text field.
In JavaScript, instead of writing:
getValue: "name"
You can write something similar to:
getValue: function (element) {
return element.lang+ element.ide
}
You can follow the discussion on this github link.
Related
I am new to stimulus. I am trying to add up number/currency inputs and display in another field (the fields are decimal attributes) as the user types in their values but I can't get it to work.
Here I want to add 'land cost' + 'prof services' and display it in 'total cost' field.
My controller:
cost_calculate.controller.js
import { Controller } from 'stimulus'
export default class extends Controller {
static targets = [ 'landCost', 'profServices', 'totalCost' ]
updateTotalCost () {
const totalCost = this.landCost() + this.profServices()
this.totalCostTarget.value = Number(totalCost).toFixed(2)
}
landCost () {
return parseInt(this.landCostTarget)
}
profServices () {
return parseInt(this.profServicesTarget)
}
totalCost () {
return parseInt(this.totalCostTarget)
}
}
My form:
<%= simple_form_for #project, html: { "data-controller" => "cost-calculate" }, url: wizard_path(step, project_id: #project.id) do |f| %>
<%= f.text_field :land_cost, data: { target: 'cost-calculate.landCost', action: "change->cost-calculate#updateTotalCost" }, class: "project-dropdown-width" %>
<%= f.text_field :prof_services, data: { target: 'cost-calculate.profServices', action: "change->cost-calculate#updateTotalCost" }, class: "project-dropdown-width" %>
<%= f.text_field :total_cost, data: { target: 'cost-calculate.totalCost' }, label: false, class: "project-dropdown-width" %>
<% end %>
It keeps printing NaN in the 'totalCost' field. I'm not entirely confident my code is right in controller or view either for what I want to do.
For example, I want to achieve this but just adding two fields together
https://ngaunhien.net/blog/simple-input-calculation-with-stimulusjs
Would appreciate any guidance. ty.
You should use the value and parse and set the default value of 0 if no value exists.
You should modify the controller as
import { Controller } from 'stimulus'
export default class extends Controller {
static targets = [ 'landCost', 'profServices', 'totalCost' ]
updateTotalCost () {
const totalCost = this.landCost() + this.profServices()
this.totalCostTarget.value = Number(totalCost).toFixed(2)
}
landCost () {
return parseInt(this.landCostTarget.value || 0)
}
profServices () {
return parseInt(this.profServicesTarget.value || 0)
}
totalCost () {
return parseInt(this.totalCostTarget.value)
}
}
I have a page that does a search, using javascript, and I want to take the list of users that it comes up with, and send that as a submit to the next page. What I have, is:
.search_client_users
= form_tag admin_clients_path, method: "get" , class: "search_form" do
= label_tag 'search_term', 'Old domain name:'
= text_field_tag 'search_term', nil, autocomplete: "off", size: "50"
.main_form.client_emails
= simple_form_for(:domainNameSwap, url: { action: "update" }, html: { method: :put }) do |f|
.input-row
= f.hidden_field :users, value: #clients
.submit-row
.row
.col-xs-5
.submit
= f.submit "Update domains", id: "submit", :class => "btn btn-primary submit"
.client_list
- content_for :javascript do
= javascript_include_tag 'admin/search_client_users'
[some of the formatting may not be quite right due to cut and paste, sorry]
The admin/search_client_users creates an #clients, I'm pretty sure, at least, with:
class App.ClientUserList
constructor: ->
#incrementalSearchAttempts = 0
search: (searchTerm, completeCallback) =>
handleResponseWithOrderAwareness = (attemptNumber, response) =>
if attemptNumber >= #incrementalSearchAttempts
completeCallback(response)
#incrementalSearchAttempts++
onComplete = _.partial(handleResponseWithOrderAwareness, #incrementalSearchAttempts)
$.get('/admin/manage_clients/client_list', { search_term: searchTerm }).complete(onComplete)
class App.Views.SearchClientUsers extends Backbone.View
events:
"keyup input[name='search_term']": "search",
"click .profile_attribute": "showClientUserProfile"
initialize: =>
#clientUserList = new App.ClientUserList()
search: =>
searchTerm = $('.search_form input[name=search_term]').val()
#clientUserList.search(searchTerm, #render)
showClientUserProfile: (event) =>
window.location = $(event.currentTarget).closest('tr').data('client-path')
render: (response) =>
#$el.find('.client_list').html(response.responseText)
$ ->
new App.Views.SearchClientUsers(el: $('.search_client_users')).search()
so, I'm trying to take the list of clients, and send it to the update method in the controller. However, due to when javascript and ruby take place, it doesn't seem to be working... is there a way to do this? or do I have to figure out how to do this in Ajax?
ETA: An alternative idea is, I suppose to just turn the initial text_field into a form, so that the text field is used both for the javascript, and THEN submitted to the form, and then the update can re-do the search... My dataset is small enough that doing the search twice is not a huge problem I suppose...
But I'm not quite sure exactly how to merge the two forms...
I am working on rails 5 app. i am trying to load the data asynchronously form pgsql using jquery-select2 data is loading perfectly on search. but the problem is, i want to show the select2 tag when radio button is selected. i have two [radio buttons][1]. code for radio buttons is following
`
<%= radio_button(:new, :agent, :yes, { required: true, checked: true,
class: 'invite-rb' }) %>
<%= label_tag :new_agent_yes, 'New Agent' %>
<%= radio_button(:new, :agent, :no, { required: true, class: 'invite-rb' }) %>
<%= label_tag :new_agent_no, 'Existing Agent' %>`
I want to show the select2 box when user clicks on existing agent. but jquery-select2 is not applied to the select box.
here is my code for agent.js
$(document).on('turbolinks:load', function() {
$('.invite-rb').change(function() {
if(this.value == 'yes'){ //when i change this value to 'no' every thing works perfectly but not working with this condition
$('#agents').removeAttr('required')
$('#agent_first_name, #agent_last_name, #agent_email, #agency_code, #agent_code').attr('required', true)
$('#existing-agent-fields').addClass('hidden')
$('#new-agent-fields').removeClass('hidden')
$('#applications-div').addClass('hidden')
}
else{
$('#agent_first_name, #agent_last_name, #agent_email, #agent_agency_code, #agent_agent_code').removeAttr('required')
$('#agents').attr('required', true)
$('#existing-agent-fields').removeClass('hidden')
$('#new-agent-fields').addClass('hidden')
$('.chosen-select').select2()
$('#applications-div').addClass('hidden')
$('.chosen-select').select2({
minimumInputLength: 2,
placeholder: "Search by Agency code, agent code, name or email",
ajax: {
url: "/dashboard/agent_invitations/search_agents",
dataType: 'json',
type: 'GET',
data: function (term) {
return { q: term }
},
processResults: function (data) {
return { results: data.results }
}
}
});
}
});
i don't know whats wrong with this conditions. i don't want to change the values assigned to radio buttons because complete logic of this page depends upon them.
agent.js [1]: https://i.stack.imgur.com/AYrel.png
I've got a collection of models with different properties and I need to render some of them inside the <select> tag, each model as an <option>. The view that renders this collection is nested in another view. Here is my collection:
var UserCollection = Backbone.Collection.extend({
url: 'http://localhost:3000',
developers: function () {
var developers = this.where({role: "developer"});
return new UserCollection(developers);
}
});
And this is my view for the select tag:
var InterviewersView = Backbone.View.extend({
initialize: function () {
this.template = _.template(interviewersTemplate);
this.collection = new UserCollection();
this.collection.fetch();
this.interviewers = this.collection.developers();
},
render: function () {
this.$el.html(this.template());
return this;
}
});
and this is my template:
<label>Interviewer</label>
<select class="form-control" id="js-interviewer-selector">
<% _.each(this.interviewers.toJSON(), function(interviewer) { %>
<option value="<%= interviewer.login %>">
<%= interviewer.firstName %> <%= interviewer.lastName %>
</option>
<% }) %>
</select>
The template renders inside another view properly and exactly as I need, but there's no options inside the select tag and it is empty. What am I doing wrong?
Repo with my project
Try to pass your collection to your view like this
render: function () {
var that = this;
that.$el.html(that.template({interviewers: that.interviewers}));
return this;
}
and in your template use underscore _.each function to dive collection to individual interviwer like this
<select class="form-control" id="js-interviewer-selector">
<% _.each(interviewers, function(interviewer) { %>
<option value="<%= interviewer.login %>">
<%= interviewer.firstName %> <%= interviewer.lastName %>
</option>
<% }) %>
</select>
It must work now:)
So, the problem was the same as in this question -- because of asynchronous nature of .fetch() method the collection was loaded after the view was rendered, so it received nothing. So, removing .fetch() method from initialize and adding it to render worked. Here's the complete code:
var InterviewersSelect = Backbone.View.extend({
initialize: function () {
this.template = _.template(interviewersTemplate);
this.collection = new UserCollection();
},
render: function () {
var self = this;
this.collection.fetch({
data: {
role: "developer"
},
success: function(collection) {
var interviewers = collection.map(function(item) {
return item.toJSON();
});
self.$el.html(self.template({interviewers: interviewers}));
}
});
return this;
}
});
I'm new to Backbone. here is my model:
window.Image = Backbone.Model.extend({
defaults: {
id: "",
url: ""
}
});
window.ImageCollection = Backbone.Model.extend({
model: Image
});
window.TargetDemoGraphic = Backbone.Model.extend({
defaults: {
targetDemographicId: "",
targetDemographicDescription: "",
checked: false
}
});
window.TargetDemoGraphicCollection = Backbone.Collection.extend({
model: TargetDemoGraphic,
url: ServiceUrl + "/targetDemoGraphic/getAll"
});
window.Promotion = Backbone.Model.extend({
url: function() {
return ServiceUrl + "/promotion/get/" + encodeURIComponent(this.id);
},
defaults: {
id: "",
item: Item,
start: "",
end: "",
title: "",
newPrice: "",
shortContent: "",
detailContent: "",
minLoyaltyPoint: "",
membershipRequired: "",
loyaltyPointRequired: "",
loyaltyPointExchangeRequired: "",
displayOnBanner: "",
images: ImageCollection,
bannerImage: Image,
targetDemoGraphics: TargetDemoGraphicCollection
}
}
window.PromotionCollection = Backbone.Collection.extend({
model: Promotion,
url: ServiceUrl + "/promotion/getAll"
});
My problem is when printing out the nested collection targetDemoGraphics in the template, the length of the collection is always 0.
I'm so confused because the nested collection images work well, it returns correct value.
My backbone view:
window.PromotionReview = Backbone.View.extend({
initialize : function(options) {
_.bindAll(this, 'beforeRender', 'render', 'afterRender');
var _this = this;
this.render = _.wrap(this.render, function(render) {
_this.beforeRender();
render();
_this.afterRender();
return _this;
});
this.render();
},
beforeRender : function() {
},
render : function() {
var promotion = this.model.toJSON();
//promotion.targetDemoGraphics.length returns = 4
//promotion.images.length = 4
$(this.el).html(this.template(promotion));
return this;
}
});
And the template:
<% if (targetDemoGraphics != null && targetDemoGraphics.length > 0) { %>
<% for (var idx in targetDemoGraphics) { %>
<p><%= targetDemoGraphics[i].label %></p>
<% } %>
<% } %>
//targetDemoGraphics.length = 0???
...
<% if (images != null && images.length > 0) { %>
<% for (var idx in images) { %>
<a href="<%=ServiceUrl + '/images/' + images[idx].url %>" data-gallery>
<img style="min-height:100px;height:100px;min-width:100px;width:100px;" src="<%=ServiceUrl + '/images/' + images[idx].url %>">
</a>
<% } %>
<% } %>
//images.length = 4, correct value ???
When printing out the promotion, I got 2 targetDemoGraphics, one contains 4 objects, other one is a function???
If you are nesting collections you better try and use some Backbone extension. Check Backbone Associations. Using some extension would help you in binding events on the nested Models and Collections as well and definitely other advantages.