Good day,
I managed to keep Redactor loaded when interacted with other parts of the app (for example: Form Inputs). This is how I load and inject Redactor at the moment:
<div>
<div class="mt-1"
x-data="{
value: '',
init() {
let redactor = new Redactor(this.$refs.redactor , {
lang: '{{ app()->getLocale() }}',
minHeight: '300px',
imageUpload: '{{ route('redactor.store', ['_token' => csrf_token()]) }}',
imageManagerJson: '{{ route('redactor.index') }}',
plugins: [
'imagemanager'
],
}, this.value)
}
}"
wire:ignore
>
<textarea id="content" rows="10" x-ref="redactor" wire:model="content"></textarea>
</div>
</div>
But when I type something inside the editor, it doesnt update the property.
If I change the property via DevTools and switch to source/editor view, it loads the data.
Maybe I oversee something, for example a API method to send the data to the textarea back?
Official docs: https://imperavi.com/redactor/docs/
Hope someone here can help with this problem :)
Greetings Syntafin
Related
Using Kendo UI JQuery Editor control, How I can write html document as a template with predefined fields that get data from database ?
For example if user typed Name:[fname] [lname]
It get replaced with first and last name data from database. I use PHP.
The Editor provides reference to the HTML element which represents the editor's content area. You can therefore set the content of the DOM elements in the Editor's content:
<input id="ddl" />
<textarea id="editor" rows="10" cols="30" style="width:100%; height:450px" aria-label="editor">
<div >
<div>Hello <span id="fname" contenteditable="true">___</span>,</div>
</br>
<div>your email is: <span contenteditable="true" id="email">___</span></div>
</div>
</textarea>
<script>
$(document).ready(function () {
// create Editor from textarea HTML element with default set of tools
$("#editor").kendoEditor({
resizable: {
content: true,
toolbar: true
}
});
//make the editor content non-editable and only some elements editable by setting the contenteditable attribute for the desired elements
var editor = $("#editor").data("kendoEditor"),
editorBody = $(editor.body);
editorBody.attr("contenteditable", false)
$("#ddl").kendoDropDownList({
optionLabel:"--Select user--",
dataTextField:"user",
dataValueField:"id",
dataSource:[
{id:1, user: "John", fname:"John",lname:"Doe",email:"john#email.com"},
{id:2, user: "Jane", fname:"Jane",lname:"Smith",email:"jane#email.com"}
],
change:function(e){
var item = e.sender.dataItem();
editorBody.find("#fname").text(item.fname);
editorBody.find("#email").text(item.email);
}
})
});
</script>
Here is an example
In my Laravel 5.7 application I use laravel-jsvalidation plugin( https://github.com/proengsoft/laravel-jsvalidation/wiki/Basic-Usage )
and it worked ok,
I needed to including textarea input as tinyMCE editor and to use i with validation and I implemented it with 2 textarea inputs :
<div class="form-row mb-3 {{ in_array('description', $errorFieldsArray) ? 'validation_error' : '' }}">
<label class="col-xs-12 col-sm-4 col-form-label">Description</label>
<div class="col-xs-12 col-sm-8">
<span style="display: inline;">
{{ Form::textarea('description', isset($vote->description) ? $vote->description : '', [ "class"=>"form-control editable_field textarea_input ", "rows"=>"0", "cols"=> 120, "id"=>"description", "autocomplete"=>"off", "style"=>"width:0; height:0" ] ) }}
</span>
{{ Form::textarea('description_container', isset($vote->description) ? $vote->description : '', [ "class"=>"form-control editable_field textarea_input ", "rows"=>"5", "cols"=> 120, "id"=>"description_container", "autocomplete"=>"off" ] ) }}
</div>
</div>
where 1st textarea is for form submitting, as entered content is copied into it from 2nd textarea, which is used as
tinyMCE editor.
In tinyMCE definition I added rows:
setup: function (editor) {
editor.on('change', function () {
var current_context= tinymce.get(by_selector_container).getContent()
$('#' + by_selector).html( current_context );
});
},
where by_selector_container and by_selector are names of these textarea inputs. It works, but the only problem that on page I can see 1st textarea input,
despite I try to hide it setting wight/height in 0 in style of my code above, but anyway I still see small textarea input : https://imgur.com/a/43FRFJU
I tried in declaration of the 1st textarea input to set
"style"=>"display:none"
Than textarea input was hidden but validation does not work at all.
How to hide it this small textarea input with validation working?
Thanks!
You can try style:
visibility: hidden ;
With the fine-uploader plugin I am trying to add multiple (dynamic could be 1, or 10) instances with an optional caption field and a manual upload button per section.
The form I am uploading from is dynamically generated in layout as well as content, the uploaded files have to be stored by the handler based upon the section of the form as well as the instance of fine-uploader. I also need the ability to effectively upload each instance of fine-uploader independently
The issue that I am hitting is following the guidelines & demo for the manual upload option, ie adding a click function it will always find only the first instance as it searches for the button using .getElementById.
I can get around this by defining a new template for each instance however I would prefer to use a single template.
The template code (for each instance - abbreviated for simplicity) is
<script type="text/template" id="qq-template-manual-trigger#XX#">
<div class="qq-uploader-selector qq-uploader" qq-drop-area-text="Drop files here">
...
<div class="buttons">
<div class="qq-upload-button-selector qq-upload-button">
<div>Select files</div>
</div>
<button type="button" id="trigger-upload#XX#" class="btn btn-primary">
<i class="icon-upload icon-white"></i> Upload
</button>
</div>
...
<ul class="qq-upload-list-selector qq-upload-list" aria-live="polite" aria-relevant="additions removals">
<li>
...
<input class="caption" tabindex="1" type="text">
...
</li>
</ul>
...
</div>
</script>
<div id="fine-uploader-manual-trigger#XX#"></div>
and the uploader script
<script>
var manualUploader#XX# = new qq.FineUploader({
element: document.getElementById('fine-uploader-manual-trigger#XX#'),
template: 'qq-template-manual-trigger#XX#',
request: {
inputName: "imagegroup[]",
endpoint: '/SaveFile.aspx'
},
autoUpload: false,
debug: true,
callbacks: {
onError: function(id, name, errorReason, xhrOrXdr) {
alert(qq.format("Error on file number {} - {}. Reason: {}", id, name, errorReason));
},
onUpload: function (id) {
var fileContainer = this.getItemByFileId(id)
var captionInput = fileContainer.querySelector('.caption')
var captionText = captionInput.value
this.setParams({
"descr[]": captionText,
<-- Other parameters here -->
}, id)
}
},
});
qq(document.getElementById("trigger-upload#XX#")).attach("click", function () {
manualUploader#XX#.uploadStoredFiles();
});
</script>
in the ideal world I would prefer simply have a single
<script type="text/template" id="qq-template-manual-trigger">
....
</script>
then where required multiple times through the form
<div id="fine-uploader-manual-trigger"></div>
<script>
var manualUploader#XX# = new qq.FineUploader({
element: document.getElementById('fine-uploader-manual-trigger'),
template: 'qq-template-manual-trigger',
...
}
qq(document.getElementById("trigger-upload")).attach("click", function () {
manualUploader#XX#.uploadStoredFiles();
});
</script>
The use of the attach function by calling .getElementById just feels wrong, or at the very least cludgy, is there a better way of activating the upload on a per-instance basis?
Thanks in advance
K
Sorted, but if anyone has a better answer...
Instead of using the demo of document.getElementById("trigger-upload")
Simply use document.querySelector("#fine-uploader-manual-trigger #trigger-upload")
eg
<div id="fine-uploader-manual-triggerXX"></div>
<script>
var manualUploaderXX = new qq.FineUploader({
element: document.getElementById('fine-uploader-manual-triggerXX'),
template: 'qq-template-manual-trigger',
... // omitted for brevity
}
qq(document.querySelector("#fine-uploader-manual-triggerXX #trigger-upload")).attach("click", function () {
manualUploaderXX.uploadStoredFiles();
});
</script>
Please note, I'm using the Laravel framework.
Also please note, there are similar questions on SO, I've checked them, but wasn't able to solve my problem based on those solutions...
Even though I set my CSRF token right to my knowledge, I'm not sure why it won't work.
When checking the console, it seems I have 3 cookies: two Request cookies of which one is called XSRF-TOKEN and one is called laravel_session. And one respone laravel_session cookie. All have a different value!!!
My Vue:
new Vue({
el:'body',
http: {
root: '/root',
headers: {
'X-CSRF-Token': $('meta[name=_token]').attr('content')
}
},
});
My head:
<meta name="_token" content="{!! csrf_token() !!}"/>
My Vue component addNew method:
Vue.component('things',{
template:'#things-panel-template',
data(){
return {
list: [],
newThing: {
body: '',
// _token: $('meta[name=_token]').attr('content'),
// tried removing token from head meta and adding up here.
},
}
},
methods:{
addNew(){
var thing = this.newThing; // get input
this.newThing = {body:''}; // clear input
this.$http.post('/api/things/add',thing) // send
},
},
});
My route:
Route::post('/api/things/add',function(){
return App\Thing::create(Request::get());
});
And finally, the form in my Vue Template:
<form action="/things/add"
method="POST"
#submit.prevent="addNew"
>
<div class="form-group">
{{ csrf_field() }}
<label for="">Add</label>
<input type="text"
name="body"
id="task-body"
class="form-control"
v-model="newThing.body"
>
<button :disabled="!isValid"
class="btn btn-primary"
type="submit"
>Add</button>
</div>
</form>
Try this:
this.$parent.$http.post('/api/things/add', thing)
instead of
this.$http.post('/api/things/add', thing)
Or set default values using the global configuration:
Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name=_token]').attr('content');
I found the answer myself:
If you're gonna work with a vue-component, you should just add the token to that component instead. Otherwise it won't go with your ajax request.
So put this part underneath the template in the component:
http: {
root: '/root',
headers: {
'X-CSRF-Token': $('meta[name=_token]').attr('content')
}
},
Do this to check if your token was properly sent inside the headers:
Go to google chrome, open dev-tools, go to the network tab and Reload.
Make the ajax call and look at the file added in the network tab, open it and go to the 'Headers' tab.
Look at the bottom where it says: 'Request Headers' and check if the token was properly added in the request.
can we use google AJAX Language API with EXTjs?????
i have tried example for translitration i have one html file
and typemarathi.js
google.load("elements", "1", { packages: "transliteration" });
function onLoad() {
var options = {
sourceLanguage: google.elements.transliteration.LanguageCode.ENGLISH,
destinationLanguage: [google.elements.transliteration.LanguageCode.MARATHI],
shortcutKey: 'ctrl+g',
transliterationEnabled: true
};
// Create an instance on TransliterationControl with the required
// options.
var control = new google.elements.transliteration.TransliterationControl(options);
// Enable transliteration in the editable DIV with id
// 'transliterateDiv'.
control.makeTransliteratable([myname]);
}
google.setOnLoadCallback(onLoad);
it works fine.
but if i write the textfield in extjs
Ext.onReady(function(){
var form1=new Ext.FormPanel({
renderTo:document.body,
frame:true,
title:'My First Form',
widyh:250,
items:[{ xtype:'textfield', fieldLabel:'First name', name:'firstname'}]
});
});
and try to pass firstname (name attribute to control.makeTransliteratable([firstname])) then it does not work... it says invalid id error
but if i pass->(html textfiled name to it) control.makeTransliteratable([myname]) it works fine
(i want to type and display multiple nonEnglish languages data
programatically frontend i used EXTjs is there any another way to do so if yes the suggest me. pls..
Yes you can.
Besides someone should clean his code, thats hurrible.
Yes, you can. But you should know that ExtJs automatically generates identifiers for html elements:
html:
<div class="x-form-item x-form-label-left x-box-item" id="ext-gen27" style="left: 0px; top: 0px;">
<label style="width: 55px;" class="x-form-item-label" id="ext-gen28">Send To:</label>
<div style="padding-left: 60px; width: 668px;" class="x-form-element" id="ext-gen26">
<div class="x-form-field-wrap x-form-field-trigger-wrap x-trigger-wrap-focus" id="ext-gen24" style="width: 668px;">
<input type="text" name="to" id="ext-comp-1002" autocomplete="off" size="24" class=" x-form-text x-form-field x-form-focus" style="width: 651px;">
</div>
</div>
</div>
js:
....
items: [{
xtype: 'combo',
store: ['test#example.com', 'someone-else#example.com' ],
plugins: [ Ext.ux.FieldReplicator, Ext.ux.FieldLabeler ],
fieldLabel: 'Send To',
name: 'to'
}]
As I understand you need to translate the label. In order to do this you should get the id of the label. To do this you can use TextField's label property (myField.label.id). If you want to translate a lot of elements then probably it'll be better for you to use something like this:
var control = new google.elements.transliteration.TransliterationControl(options);
var labelIds = [];
Ext.each(Ext.select('label'), function(item){
labelIds.push(item.id);
});
control.makeTransliteratable(labelIds);
But be aware that you should call this only after rendering all elements. Also you can write a some plugin that will inject this functionality into 'render' method. Writing a plugin is a better but a bit more harder way.