rails 4 : change state issue with Bootstrap Switch - ruby-on-rails-4

I have 3 bootstrap switches to handle read/update/create permissions.
They area written as :
<%= f.check_box :allow_read, :data => { :size=>'medium',
'on-color'=>'success', 'on-text'=> "#{t('yes').upcase}",
'off-text'=> "#{t('no').upcase}" } %>
<%= f.check_box :allow_update, :data => { :size=>'medium',
'on-color'=>'success', 'on-text'=> "#{t('yes').upcase}",
'off-text'=> "#{t('no').upcase}" } %>
<%= f.check_box :allow_create, :data => { :size=>'medium',
'on-color'=>'success', 'on-text'=> "#{t('yes').upcase}",
'off-text'=> "#{t('no').upcase}" } %>
and displayed as :
I am trying to use the switchChange.bootstrapSwitch method to change other é switches when one switch is toggled by the user .
When :allow_read is switch OFF , then :allow_update and :allow_create should be switched OFF too...
So I wrote the following js code to handle this case ...
$('input[name="permission[allow_read]"]').on('switchChange.bootstrapSwitch', function(event, state) {
if (event.type == "switchChange" && state == false){
$('input[name="permission[allow_update]"]').bootstrapSwitch('state', false, true); // disallow update
$('input[name="permission[allow_create]"]').bootstrapSwitch('state', false, true); // disallow create
}
});
But it's not working fine ... as it's inserting and OFF text before the switch, however the toggling is performed :
what could be wrong ?
thanks for feedback
--UPDATE ---
forgot to add the generated HTML...
<div class="col-sm-9">
<input name="permission[allow_read]" type="hidden" value="0">
<div class="bootstrap-switch bootstrap-switch-wrapper bootstrap-switch-on bootstrap-switch-medium bootstrap-switch-animate bootstrap-switch-id-permission_allow_read">
<div class="bootstrap-switch-container">
<span class="bootstrap-switch-handle-on bootstrap-switch-success">OUI</span>
<label class="bootstrap-switch-label"> </label>
<span class="bootstrap-switch-handle-off bootstrap-switch-default">NON</span>
<input type="checkbox" value="1" checked="checked" name="permission[allow_read]" id="permission_allow_read">
</div>
</div>
</div>

I guess there is something wrong with html generated by the Rails view helper and Bootstrap switch...
back to a standard html tag , it works correctly
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<p class='col-sm-3 control-label' >READ</p>
<div class="col-sm-9">
<input id="allow_read" name="permission[allow_read]" type="checkbox" value="1" data-size ='medium', data-on-color ='success' data-on-text = "YES" data-off-text = "NO" />
</div>
</div>
</div>
</div>
and similar switches for update and create.... the js script runs very well...

Related

In listing of data form is rendered when any input edited?

with livewire 1.3 / alpinejs 2.x.x I make listing of data with filter text
and selection inputs and clicking on “Search” button I need to run search when
“Search” button is clicked.
But search is run when text/selection input lose focus without clicking on “Search” button.
I see it by form's wire:loading block and 1 line in log file, which I trigger in render method
That is not what I need : I need to run render method only clicking on “Search” button.
I tried to use alpinejs, but failed...
In component app/Http/Livewire/Admin/AppNews.php I have:
<?php
namespace App\Http\Livewire\Admin;
use Carbon\Carbon;
use Livewire\Component;
use App\News;
use Livewire\WithPagination;
use Livewire\WithFileUploads;
class AppNews extends Component
{
use WithPagination;
use WithFileUploads;
public $filters = [
'title' => '',
'published' => '',
];
];
public $uploaded_file_name;
public $uploadedImageFilenameData;
public $uploadedNewsImage;
protected $listeners = ['fileUpload' => 'handleFileUpload'];
public $current_news_id;
public $updateMode = 'browse';
public function render()
{
\Log::info('-1 NewsRENDER $this->filters ::' . print_r($this->filters, true));
$news_rows_count = News
::getByTitle($this->filters['title'], true)
->getByPublished($this->filters['published'], true)
->count();
$backend_per_page = Settings::getValue('backend_per_page', CheckValueType::cvtInteger, 20);
$this->emit('app_news_opened', ['mode' => 'browse', 'id' => null]);
$newsPublishedValueArray = SetArrayHeader([['key' => '', 'label' => ' -Select published- ']], News::getNewsPublishedValueArray(true));
$newsDataRows = News
::getByTitle($this->filters['title'], true)
->getByPublished($this->filters['published'], true)
->with('creator')
->orderBy('news.created_at', 'desc')
->paginate($backend_per_page);
$newsDataIds = [];
foreach ($newsDataRows as $nextNews) {
$newsDataIds[] = $nextNews->id;
}
return view('livewire.admin.app-news.container', [
'newsDataRows' => $newsDataRows,
'newsDataIds' => $newsDataIds,
'form' => $this->form,
'news_rows_count' => $news_rows_count,
'newsPublishedValueArray' => $newsPublishedValueArray,
]);
}
and in the template resources/views/livewire/admin/app-news/container.blade.php :
<article class="admin_page_container">
<div class="card form-admin-news">
<div class="card-body card-block">
<div class="spinner-border" role="status" wire:loading>
<span class="sr-only">Loading...</span>
</div>
...
<fieldset class="bordered text-muted p-2 m-2" x-data="{ title: '{{$filters['title']}}', published: '{{$filters['published']}}' ,
publishedItems: <?php print str_replace('"',"'",json_encode( $newsPublishedValueArray) ) ?> } ">
<div> $filters::{{ var_dump($filters) }}</div>
title::<div x-html="title"></div>
published::<div x-html="published"></div>
<legend class="bordered">Filters</legend>
<dl class="block_2columns_md m-0 p-2">
<dt class="key_values_rows_label_13">
<label class="col-form-label" for="temp_filter_title">
By title
</label>
</dt>
<dd class="key_values_rows_value_13" >
<div class="content_with_right_button">
<div
class="content_with_right_button_left_content"
wire:model.lazy="filters.title"
>
<input
class="form-control admin_control_input"
type="text"
x-model="title"
x-on:blur="$dispatch('input', title)"
id="title"
>
</div>
<div class="content_with_right_button_right_button pl-2">
<button class="btn btn-outline-secondary nowrap_block" wire:click="makeSearch( )">
{!! $viewFuncs->showAppIcon('filter') !!}Search
</button>
</div>
</div>
</dd>
</dl>
<dl class="block_2columns_md m-0 p-2">
<dt class="key_values_rows_label_13">
<label class="col-form-label" for="temp_filter_published">
By published
</label>
</dt>
<dd
class="key_values_rows_value_13"
wire:model.lazy="filters.published"
>
<select
x-model="published"
x-on:blur="$dispatch('select', published)"
id="published"
class="form-control editable_field admin_control_input"
>
<template x-for="nextPublishedItem in publishedItems">
<option :value="nextPublishedItem.key" x-text="nextPublishedItem.label"></option>
</template>
</select>
#error('form.published')
<div class="validation_error">{{ clearValidationError($message,['form.'=>'']) }}</div> #enderror
</dd>
</dl>
</fieldset> <!-- Filters -->
...
#endif {{-- #if($updateMode=='browse')--}}
#endif {{-- #if($updateMode=='browse')--}}
#if(count($newsDataRows) > 0)
<div class="table-responsive table-wrapper-for-data-listing" x-data="selectedNewsIdsBoxXData()">
<table>
...
</table>
</div> <!-- <div class="table-responsive table-wrapper-for-data-listing"> -->
#endif {{-- #if(count($newsDataRows) > 0) --}}
#endif {{-- #if($updateMode=='browse') --}}
</div> <!-- <div class="card-body card-block"> -->
</div> <!-- <div class="card"> -->
</article> <!-- page_content_container -->
Which is the valid way?
Modified BLOCK 2:
I try another way with using of alpinejs2 : I try to use it in this case, as when public var of component is changed:
with dispatch methid when button “Search” is clicked
<div class="card form-admin-facilities" x-data="adminFacilitiesComponent()">
...
filter_name: {{$filter_name}}<br>
...
temp_filter_name: <span x-html="temp_filter_name"></span><br>
...
<fieldset class="bordered text-muted p-2 m-2">
<legend class="bordered">Filters</legend>
<div class="content_with_right_button" wire:model.lazy="filter_name">
<div class="content_with_right_button_left_content" >
<input
class="form-control admin_filter_input"
x-model="temp_filter_name"
type="text"
>
</div>
<div class="content_with_right_button_right_button pl-2" >
<button class="btn btn-outline-secondary" #click="$dispatch('input', temp_filter_name)" type="button">Search
</button>
<!-- In more complicated form can be several filter fields : text and select inputs -->
</div>
</div>
</fieldset> <!-- Filters -->
...
<script>
function adminFacilitiesComponent() {
return {
temp_filter_name:'',
and in the component I defined public $filter_name var, which is used in render method :
class Facilities extends Component
{
public $form= [
'name'=>'',
'descr'=> '',
'created_at'=> '',
'is_reopen' => false,
];
public $current_facility_id;
public $filter_name= '';
public $updateMode = 'browse';
public function render()
{
\Log::info( '-1 render Facilities $this->filter_name ::' . print_r( $this->filter_name, true ) );
$this->facility_rows_count = Facility
::getByName($this->filter_name, true)
->count();
$backend_per_page = Settings::getValue('backend_per_page', CheckValueType::cvtInteger, 20);
return view('livewire.admin.facilities.container', [
'facilityDataRows' => Facility
::orderBy('created_at', 'desc')
->getByName($this->filter_name, true)
->paginate($backend_per_page),
'facility_rows_count'=> $this->facility_rows_count
]);
}
But it does not work as I expect : entering value in text input when this input lose focus
form is rendered again. I expected form to be rendered only when I click on “Search” button
and form will be rendered with new entered value. I do not use blur event for text input and
do not understand why the form is rendered when this input lose focus?
Modified BLOCK 3:
Using x-ref= I do :
<div class="content_with_right_button" wire:model.lazy="filter_name">
<div class="content_with_right_button_left_content" >
<input
class="form-control admin_filter_input"
x-model="temp_filter_name"
x-ref="searched"
type="text"
> 1111111
</div>
<div class="content_with_right_button_right_button pl-2" >
<button class="btn btn-outline-secondary nowrap_block" wire:click="makeSearch(this.$refs.searched)" type="button">
Search
</button>
</div>
</div>
But I got error clicking on search button:
VM1983:6 Uncaught TypeError: Cannot read property 'searched' of undefined
at eval (eval at parseOutMethodAndParams (directive.js:55), <anonymous>:6:27)
at _default.parseOutMethodAndParams (directive.js:55)
Looks like it is impossible to use this.$refs. value in
wire:click="makeSearch .
I need to trigger component method
public function makeSearch($search_value='')
{
and send entered value into it.
Looks like the way I tried was invalid.
If there is a valid way?
Thanks!
In your modified block 2, you should use wire:ignore in base div of your AlpineJS component. This will make livewire ignore the component.
<div class="card form-admin-facilities" wire:ignore x-data="adminFacilitiesComponent()">
Your $dispatch() should handle setting the value when you click the button.
In order to make livewire ignore the component just add wire:ignore to your component's div in modified block 2 and then in your dispatch method you can write the logic that happens after clicking the button.

Bootstrap Datepicker goes bottom

I am not an expert in Bootstrap 3. It was my first time to use the widget "datepicker". I have two date pickers that need to be displayed inline to each other. When I try a normal input it works but if it is a date picker it goes a little far at the bottom. I tried the position relative however it did not resolve the issue. See screen shot attached.Date picker goes at the bottom
Hope some one can give me some light. Below is my code.`
<div class="horiz-search-bar-wrapper">
<form class="form-inline">
<div class="form-group">
<label><strong>Search</strong></label>
</div>
<div class="input-daterange">
<div class="form-group rel-position-date">
<label>Check-In:</label>
<div class="input-group input-append date" id="from">
<input type="text" class="form-control">
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</div>
<div class="form-group rel-position-date">
<label>Check-Out</label>
<div class="input-group input-append date" id="to">
<input type="text" class="form-control">
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group mar-left">
<button type="button" class="btn btn-primary">
Submit
</button>
</div>
</form>
</div>
`
Just an update to this, we were able to fixed the issue by replacing the <label></label> tag to <span></span>. The bootstrap datepicker adds top pixels when it sees more than 1 label.
Hope this could help the others.
I was also seeing issues with the Datepicker appearing too low. Whether the targeted element was toward the top or bottom of the viewport and the Datepicker was respectively orienting itself above or below the element, I was seeing a Datepicker appear "too-low."
Stumbled on to a fix with some JavaScript hackery bound to the DP's "show" event/hook.
Note the use of the native Boostrap CSS utility classes datepicker-orient-top and datepicker-orient-bottom.
$('#DateOfBirthForEditing').datepicker().on("show", function (e) {
var refDatePicker = $('div.datepicker.datepicker-dropdown');
var refDatePickerField = $('#DateOfBirthForEditing');
var fieldPositionTop = refDatePickerField.offset().top;
var dpModalTopOffset = 0;
if (refDatePicker.hasClass('datepicker-orient-top')) {
dpModalTopOffset = fieldPositionTop - 255;
} else if (refDatePicker.hasClass('datepicker-orient-bottom')) {
dpModalTopOffset = fieldPositionTop + 30;
}
refDatePicker.css({ "top": dpModalTopOffset });
});

Django 1.9, how to POST multiple select value from html

UPDATE:
I found an answer. Just added this little code at the bottom:
$('#myform').submit(function()
{
$('#dates option').prop('selected', true);
});
I have a tempate:
div class="panel">
<div class="large-12 columns">
<div class="row collapse">
<div class="small-10 columns">
<input class="input-append date fdatepicker" id="date" type="text" name="date" value="" data-date-format="dd/mm/yyyy">
</div>
<div class="small-2 columns">
<input type="button" name="add" id="btn_AddToList" value="dodaj" class="button postfix" />
</div>
</div>
</div>
<br>
<select multiple="multiple" size="10" style="height: auto; width: auto" name="dates" id="dates" tabindex="2">
</select>
</div>
and I add dates to #dates select using this little code:
$('#btn_AddToList').click(function () {
var val = $('#date').val();
$('#dates').append('<option value="'+val+'">' + val + '</option>');
$('#date').val('');
event.preventDefault();
event.stopPropagation();
})
in my view i want to read dates so i thought i would use:
for d in request.POST.getlist('dates'):
if d is not None:
print(d)
But I get None. I tried to use request.POST.getlist('dates[]'): request.POST.get('dates'): but with no success. I am recieving None all the time.
What I am doing wrong?
UPDATE: I found an answer. Just added this little code at the bottom:
$('#myform').submit(function()
{
$('#dates option').prop('selected', true);
});

Display the error message after the label title

I had the form using the simple form like this:
<%= f.input :last_name %>
When there is validation error on form the validation error message are display after the input text box like this:
<div class="input string required test_last_name field_with_errors"><label class="string required" for="test_last_name"><abbr title="required">*</abbr> Last name</label>
<input class="string required" id="test_last_name" name="test[last_name]" type="text" value="">
<span class="error">can't be blank</span>
</div>
I would like to generate html like below to display the message after the label :
<div class="input string required test_last_name field_with_errors"><label class="string required" for="test_last_name"><abbr title="required">*</abbr> Last name</label> <span class="error">can't be blank</span>
<input class="string required" id="test_last_name" name="test[last_name]" type="text" value="">
</div>
Any help will be really appreciated.
Thanks
Sabbu
This is a long shot, but try
<%= f.input :last_name as: :required %>
I put 2 and 2 together that this was a ruby project after the fact.
<div class="input string required test_last_name field_with_errors"> <label class="string required" for="test_last_name"><abbr title="required">*</abbr> Last name</label><span class="error"> can't be blank</span>
<input class="string required" id="test_last_name" name="test[last_name]" type="text" value="">
</div>
I found the answer and I am posting here so that it might help somebody.
In the simple for configuartion file just put the error tag before input like this :
b.use :error, wrap_with: { tag: :span, class: :error }
b.use :label_input
And add this css on error class:
float:right
Thanks
Sabbu

Angular: Building a directive and remove attribute from root element

Is it possible to do something like this:
<field:text id="foo" label="Foo Label" model="model.foo" placeholder="foo" />
which would be compiled to:
<div class="control-group">
<label class="control-label" for="foo">Foo Label</label>
<div class="controls">
<input type="text" id="foo" placeholder="foo" ng-model="model.foo">
</div>
</div>
I tried to make a example, but Plunker wouldn't let me save my example... uploaded it to dropbox: https://dl.dropbox.com/u/2862814/plunk.zip
The example breaks with stuff like ng-change. This is due the compilation of the ng-change directive. I tried it with a high priority to the fieldText directive, but doesn't fix it.
You were pretty close with in your example, but you have to put ng-change on the input-field in the template. Your old code:
<field:text ng-change="updateHidden()" ...
Change this to
<field:text change="updateHidden()" ...
and in the directive (see http://docs.angularjs.org/guide/directive - & or &attr - provides a way to execute an expression in the context of the parent scope.)
{scope:{change:'&' ...
and finally the directive template
<input ng-change="change()" ...
Here is a modiefied and working plunkr: http://plnkr.co/edit/QmQjGQQBRtDmkCka0dul?p=preview
<field:text id="too" label="Too" model="model.too" placeholder="too" change="updateHidden()"></field:text>
<script type="text/ng-template" id="/tpl.html">
<div class="control-group">
<label class="control-label" for="{{id}}">{{label}}</label>
<div class="controls">
<input ng-change="change()" type="text" id="{{id}}" placeholder="{{placeholder}}"
ng-model="model">
</div>
</div>
</script>
directive('fieldText',function(){
return {
restrict:'E',
templateUrl:'/tpl.html',
scope:{change:'&',id:'#',model:'=',placeholder:'#',label:'#'}
}
})