Display only three inputs in your dropdown using selectize.js - javascript

I am using selectize.js for a nice dropdown, however I'm trying to show only three results when its dropped down instead of the full 20 that I've got. Thus, when a user wants to find something he needs to type unless they are one of the first three. I'm still new to Javascript and I couldn't find an answer in other questions that helped. I've put my relevant code below. Thank you so much!!
HTML
<div class="field">
<%= f.label :homecity, "Home Town" %><br>
<%= f.select :homecity_id, Homecity.all.pluck(:Hometown, :id), {}, { class: "selectize1" } %>
</div>
Edit.js
$(document).on("turbolinks:load", function() {
var selectizeCallback = null;
$(".homecity-modal").on("hide.bs.modal", function(e) {
if (selectizeCallback != null) {
selectizeCallback();
selecitzeCallback = null;
}
$("#new_homecity").trigger("reset");
$.rails.enableFormElements($("#new_homecity"));
});
$(".selectize1").selectize({
create: function(input, callback) {
selectizeCallback = callback;
$(".homecity-modal").modal();
$("#homecity_Hometown").val(input);
}
})
});

selectize takes an option parameter for "maxOptions" that provides what you want.
for example:
$(“.selectize1”).selectize({maxOptions: 3});

Related

Rails + StimulusJS dynamically created select menu doesn't work

I'm dynamically adding fields to my form. In case of a standard text field it works fine with Rails + StimulusJS with an <template> element.
I'm using MaterializeCSS for styling and if I try to do the same thing with a select menu, it breaks and it seems the innerHTML I get back in my JS code doesn't match the code inside the template-tag. So I decided to use a div instead which I duplicate.
The view code (the relevant part):
<div data-nested-form-target="template">
<%= f.fields_for :stations, department.stations.build, child_index: "NEW_RECORD" do |station| %>
<%= render "admin/departments/stations/station_fields", f: station %>
<% end %>
This is the template I duplicte in my Stimulus controller.
This is what the first (and working) select menu looks like in HTML:
So the next step was to change the ID'S of the <ul> and the two <li> elements + the data-target element to target the right select menu.
What I ended up was this JS-Code, which is indeed adding a second select menu with the right styles, but it is not clickable and doesn't show options, despite they exist in the HTML markup and the ID's differ from the first one:
add_association(event) {
event.preventDefault()
let random_id = this.generate_random_id()
let content = this.templateTarget.cloneNode(true)
content.getElementsByTagName("ul").item(0).setAttribute("id", random_id)
content.getElementsByClassName("dropdown-trigger").item(0).setAttribute("data-target", random_id)
let list_elements = Array.from(content.getElementsByTagName("ul").item(0).querySelectorAll("li"))
list_elements.forEach((item) => {
let rnd = this.generate_random_id()
item.setAttribute("id", rnd)
})
let html = content.innerHTML.replace(/NEW_RECORD/g, new Date().getTime())
this.linksTarget.insertAdjacentHTML("beforebegin", html)
console.log(html)
let collection = this.basicTarget.getElementsByClassName("nested-fields")
let element = collection[collection.length - 1].getElementsByClassName("animate__animated")[0]
element.classList.add(this.fadeInClass)
}
Now it looks like this and I can't figure out how to make this thing working:
We're using the same stack (Rails, Stimulus.js, Materialize) with no problem. One thing you have to do after updating the select is re-initialize the Materialize select. For example, this is a general purpose nested select controller in which different sub-selects become active based on the parent select:
import { Controller } from 'stimulus';
import Materialize from 'materialize-css';
export default class extends Controller {
static targets = [
'childSelect',
]
parentSelectChanged (e) {
const selectedParentMenu = e.target.value;
this.childSelectTargets.forEach(selectElement => {
if (selectElement.dataset.parentMenuName === selectedParentMenu) {
selectElement.disabled = false;
selectElement.value = '';
} else {
selectElement.disabled = true;
}
Materialize.FormSelect.init(selectElement);
});
}
}
And here is the corresponding Haml:
.input-field.col
= select_tag :category,
options_for_select(grouped_conditions.keys.sort, selected_parent_menu_name),
include_blank: 'Select One...',
data: { action: 'nested-select#parentSelectChanged' }
.input-field.col.hide-disabled
- grouped_conditions.each do |parent_menu_name, child_conditions|
= f.select :condition_id,
options_for_select(child_conditions.sort_by(&:menu_name).map{ |tc| [tc.menu_name, tc.id] }, selected_condition_id),
{ include_blank: 'Select One...' },
disabled: selected_parent_menu_name != parent_menu_name,
data: { 'nested-select-target' => 'childSelect', 'parent-menu-name' => parent_menu_name }
= f.label :condition_id

Remove form input based on value in simple form collection

In my rails app I have a lesson model that belongs to a course. In the lesson new page, there is a collection of courses that can be selected for the lesson. Courses have several 'course_types' but the most important one for this question is the 'physical' course_type. This is the sample code
<%= f.association :course, collection: current_academy.courses.collect
{ |u| [u.title, u.id] }, prompt: t("select") %>
On the same page, you can add a video link to the lesson
<%= f.input :video, label: t(".vimeo_link_to_video") %>
I want to be able to remove the video link if the course_type is 'physical'.
In my js, I have
document.addEventListener('DOMContentLoaded',function() {
document.querySelector('select[name="lesson[course_id]"]').onchange=changeEventHandler;
},false);
function changeEventHandler(event) {
if(event.target.value == "97" ) {
$(".vimeo").hide();
}
else {
$(".vimeo").show();
}
}
At the moment, I have to enter the course id, to make it work. What i want is to be able to derive the course type dynamically. So essentially i would like to do something like this in javascript
if(event.target.value == course.physical? )
How I can remove the video form input dynamically with Javascript when the value of the course is a 'physical' course_type.

What's the best way to show and get input from text field, only when "Others" is selected on select box?

I'm using Ruby on Rails and AngularJS, and currently I'm using Angular to show the text field depending on selection. However, I'm having trouble with saving the value.
My html.haml:
%div{ "ng-app" => "formApp" }
= simple_form_for(#app) do |f|
.form-group{ "ng-controller" => "TypeCtrl", "ng-init" => "init('#{#type}')" }
= f.label :type, "Type"
= f.select :type, type_selection, { }, { required: true, class: "form-control", "ng-model" => "type_select" }
= f.text_field :type, class: "form-control", "ng-show" => "type_select=='others'"
My js.erb:
$("document").ready(function() {
formApp = angular.module('formApp', []);
formApp.controller('TypeCtrl', ['$scope', function($scope) {
$scope.init = function(type) {
$scope.type_select = type;
}
}]);
});
#type used in ng-init is defined in my controller. Currently, I've got the dropdown to display correctly on init, and it shows the text field as expected. However, it's always saving the type field as whatever is typed in, instead of looking at dropdown (probably because I have 2 input fields both for type). What is the conventional way to fix this with RoR and AngularJS?
You shouldn't have multiple inputs with the same name. It'll assign the last one. Consider changing one to e.g. type_select and the other to type_input then handle them individually on the controller side.
Rails example:
if params[:type_select] == 'Other'
type = params[:type_input]
else
type = params[:type_select]
end

Show different controls depending on rails collection select (selected) item

Sorry i couldn't get a better title to my question but hope my explanation will give you guys a better idea of what's going on?
I have a model Airport and three other models West East and South that aren't related in anyway only that Airport model needs some of the other fields like this form shows.
<%= form_for(#airport) do %>
<%= f.collection_select(:airport_name, AirPortManager.all, etc...) %>
//AirPortManager is a collection of available airports
<div class="west-airports" style="display:none;">
<%= f.collection_select(:airline_name, WestAirlineManager.all, ....) %>
</div>
<div class="east-airports" style="display: none;">
<%= f.collection_select(:airline_name, EastAirlineManager.all, ....) %>
</div>
<div class="south-airports" style="display: none;">
<%= f.collection_select(:airline_name, EastAirlineManager.all, ....) %>
</div>
<% end %>
The airport model validates :airline_name, :presence => true . Now the problem is with
my javascript. If a user selects airport west in AirPortManager.all the west-airports div` should be shown and so on. But my validation method airport keeps throwing a required field error for :airline_name and if not that it keeps a value from a previous selection. How can i pass the visible div value to airport parameters or if i select an empty value the previous value shoudn't remain constant. Below is my javascript and hope my question makes sense.
<script type="text/javascript">
$(document).ready(function() {
$("#aiport_manager_aiport_name").change(function(){
var value = this.value;
if (value == "West") {
$('.west-aiports').show();
$('.east-airports').attr("disabled", true);
$('.east-airports').hide();
$('.south-airports').attr("disabled", true);
$('.south-airports').hide();
}
else if (value == "East") {
$('.east-airports').show();
$('.west-aports').hide();
$('.west-airports').attr("disabled", true);
$('.south-airports').hide();
$('.south-airports').attr("disabled", true);
}
else if (value == "South") {
$('.south-aiports').show();
$('.west-airports').hide();
$('.west-airports').attr("disabled", true);
$('.east-airports').hide();
$('.east-airports').attr("disabled", true);
}
});
});
</script>
I try and disable the other collection_selects in their respective divs but still get a validation error or get a persistent value.
Your form has multiple elements with the same name (:airline_name), which is the core problem. You're on the right track with disabling, but you're disabling the div instead of the select. I would just do this:
// before form is submitted, disable all hidden selects
$('form').on('submit', function(e) {
$('select:hidden').prop('disabled', true);
});

Rails and jQuery: How to select input from a specific form

I have a rails app with a job model, and on the index page, each job has a form. I need to be able to access the specific form everytime the submit button is selected, so I can take the input for the form and perform some jQuery validation with it.
Here is some of my index.html page.
<ul>
<% #unassigned.each do |job| %>
<li>
<div class="row new-message">
<div class="small-12 columns">
<%= form_for #message do |f| %>
<%= f.text_area :body, {placeholder: 'enter a new message...'} %>
<%= f.hidden_field :job_id, value: job.id %>
<%= f.submit 'send message', class: 'button small radius secondary message-button', "data-job-id" => job.id %>
<div id="message<%= i %>-validation-errors"> </div>
<% end %>
</div>
</div>
<li>
<% end %>
<ul>
And here is the javascript/jQuery where I try to select the input from a specific form
var messages;
messages = function() {
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
messageValidation(e, id);
});
function messageValidation(e, id) {
var body = $('#message_body').val();
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};
$(document).ready(messages);
The index page will have a form for each job, and I want there to be front end validation that checks when the button is submitted, that the body field is not empty. It works fine the first time, but after going back to the index page, and trying to validate a second time var body = $('#message_body').val(); always seems to be empty, whether I put anything in the body or not. I believe it has something to do with the fact that since there is the same form for each job, there are multiple #message_body id's on the same page, and it is selecting the incorrect one. I am new to jQuery and javascript can someone please help me
You cannot have multiple elements with same id on a page. What you can do is add a class identifier to those elements.
In your case, simple set class="message_body" to your elements and select them as shown below:
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
var body = $(this).parent().find('.message_body').val();
messageValidation(e, body, id);
});
To solve this problem I needed to select the child of the form and find the message_body through that.
messages = function() {
$('.new_message').submit(function(e) {
//var id = $(this).data('job-id');
var $this = $(this);
var body = $this.children('#message_body').val();
var id = $this.children('#message_job_id').val();
messageValidation(e, body, id);
});
function messageValidation(e, body, id) {
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};

Categories

Resources