How to preserve formatting in a multiline <v-text-field>? - vuetify.js

I use v-text-field to gather a lengthy description from the user.
This description has line breaks but when looking at the Vue data element which holds the description I see that it is a string with just the content - the separators are gone.
Is there a way to keep the new lines in the Vue data element?

The formatting is actually present, it is just not visible when analyzing the value (string) of the bound property.
An example of reuse of a textarea content is below. Type a few lines in the first placeholder and the content will be manipulated in several ways, with formatting preserved
new Vue({
el: "#app",
data: {
comment: 'placeholder'
},
computed: {
jcomment() {
return JSON.stringify(this.comment)
},
bcomment() {
return JSON.parse(this.jcomment)
}
}
})
p {
background-color: lightgray;
padding: 5px 5px 5px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vuetify/dist/vuetify.js"></script>
<div id="app">
<p>the textarea to type into</p>
<v-text-field multi-line v-model="comment"></v-text-field>
<p>a dynamic copy of the textarea above</p>
<v-text-field multi-line v-model="comment"></v-text-field>
<p>a "pre" version of the content</p>
<pre>{{comment}}</pre>
<p>a JSON version of the content</p>
{{jcomment}}
<p>the JSON version above, parsed and displayed in a textarea</p>
<v-text-field multi-line v-model="bcomment"></v-text-field>
</div>

Related

Dynamically changing class in v-text-field in default slot

I am trying to dynamically change font-size in v-text-field default slot based on the length of the text. However, it seems that v-text-field ignores any specification I specify in the section.
Here is the code
<v-text-field
v-model="attr.name"
hide-details
:readonly="true"
class="core-select"
label="Core Attribute"
>
<template
v-slot:default
>
<div :class="attrNameStyle[0]">
{{ attr.name }}
</div>
</template>
</v-text-field>
I have verified that attrNameStyle[0] is gets set correctly, however that style never gets applied to the default slot. I can change the way input slot looks via this CSS class .v-text-field__slot input { ... } however, I can't update that CSS dynamically.
Thanks for help!
Edit: Adding more context.
.core-select {
width: 180px;
}
.short-core-select {
font-size: 12px;
}
attrNameStyle[0] is set to either '', or 'short-core-select'.
Since v-text-field__slot is working, you could edit that CSS from a higher level.
<v-text-field
v-model="attr.name"
hide-details
hide-details
class="core-select"
:class="attrNameStyle[0]"
label="Core Attribute"
>
<template>
<div>
{{ attr.name }}
</div>
</template>
</v-text-field>
<style>
.short-core-select .v-text-field__slot {
font-size: 12px;
}
</style>

How to display two data textfiled in kendo treeview in client side

I want to display name and id filed in kendo treeview. the below one is not working
$("#trainingtreelist").kendoTreeView({
dataTextField:"name"+"id",
dataSource: data
});
I have prepared a simple dojo for you showing you how to template the items being displayed in the treeview.
https://dojo.telerik.com/IsUZewoX
the important thing to look at here is the config of the treeview:
$("#treeview").kendoTreeView({
template: kendo.template($("#treeview-template").html()),
dataSource: ...remove for brevity
});
then using the template outlined here:
<script id="treeview-template" type="text/kendo-ui-template">
#: item.text # <span style="border:1px solid black; margin:3px;padding:10px; font-weight:bold; "> #:item.id#</span>
# if (!item.items) { #
<a class='k-icon k-i-close-outline' href='\#'></a>
# } #
</script>
we can restyle the items how we like. I have simply taken the demo templating example from: https://demos.telerik.com/kendo-ui/treeview/templates and added the id and styled that so it is noticeable (contained in the bordered box).

vue.js wrong transition group animation position

at first I'm css beginner
I was trying to make vue.js animation for some items and it worked well but I got wrong animation
-We have button to add element to the array randomly
-We can click at element to remove it
problem:
-The animation always run on the last item
I expected that vue js should apply animation on the item which added or removed
What is the wrong in code that make the animation go wrong ??
What should i change or add to make the animation work correctly ??
new Vue({
el: "#app",
data: {
myNumbers: [1, 2, 3, 4],
highestNumberInMyNumbers: 4
},
methods: {
addNumber() {
this.highestNumberInMyNumbers++;
this.myNumbers.splice(Math.floor(Math.random() * this.myNumbers.length), 0, this.highestNumberInMyNumbers);
},
removeNumber(element) {
this.myNumbers.splice(element, 1)
}
}
})
.mix-enter {
opacity: 0;
}
.mix-enter-active {
transition: opacity 500ms;
animation: mixing-in 600ms ease-in forwards;
}
.mix-leave {}
.mix-leave-active {
transition: opacity 1000ms;
animation: mixing-out 0.4s ease-in forwards;
opacity: 0;
}
#keyframes mixing-in {
from {
transform: translateX(-20px) translateY(20px);
}
to {
transform: translateX(0px) translateY(0px);
}
}
#keyframes mixing-out {
from {
transform: translateX(0px) translateY(0px);
}
to {
transform: translateX(-20px) translateY(-20px);
}
}
<script src="https://vuejs.org/js/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div id="app">
<h2>group transition for directive v-for </h2>
<hr>
<button #click="addNumber">Add number</button>
<br>
<br>
<div class="row">
<ul class="col-xs-4 col-sm-4 col-md-4 col-lg-4 col-xs-offset-4">
<transition-group name="mix" mode="out-in">
<li class="alert alert-success list-unstyled" style="height: 40px; padding: 10px 15px;margin-bottom: 8px;cursor: pointer;" v-for="(number,index) in myNumbers" #click="removeNumber(index)" :key="index">{{number}}
</li>
</transition-group>
</ul>
</div>
</div>
There is a bug in transition-group!
When you bind the key of li as the index, every time you remove a li, the animation always happend at the last li element.
So, if you want to use the animation with li , you can bind the key with number in your case.
<transition-group name="mix"
mode="out-in">
<li class="alert alert-success list-unstyled"
style="height: 40px; padding: 10px 15px;margin-bottom: 8px;cursor: pointer;"
v-for="(number,index) in myNumbers"
#click="removeNumber(index)"
:key="index">
{{number}}
</li>
</transition-group>
vs
<transition-group name="mix"
mode="out-in">
<li class="alert alert-success list-unstyled"
style="height: 40px; padding: 10px 15px;margin-bottom: 8px;cursor: pointer;"
v-for="(number,index) in myNumbers"
#click="removeNumber(index)"
:key="number">
{{number}}
</li>
</transition-group>
Finally, if you use animation with transition-group , do not bind the key to index , instead of item or number (in your case).
No matter what , make sure the key has the unique value.
Solution
Don't use index anywhere in the v-bind:key when using transition or transition-group.
Explanation
There is a bug/missing documentation, as well as bad documentation in the cookbook on vuejs.org, but there's a detailed explanation in the comments [1] on how indexes work, but no recognition this is a problem for developers in it's current state.
I have posted a few times to github, but the Vue.js developers there seem dismissive at best and refuse to either document this behavior or recognize this as a problem.
Reproduction of bug/error
There are three examples in the codepen below. The #1 works, the #2 uses :key="index" (your specific error above) and #3 uses :key="item +'_'+ index".
#2 and #3 give the error you are experiencing.
https://codepen.io/megacromulent/pen/wEzWNL
Summary of codepen:
This one works: (using item as :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="item">
{{item}}
</li>
</transition-group>
This one fails: (using index as :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="index" >
{{item}}
</li>
</transition-group>
This one fails worse: (concatenating index with string in :key)
<transition-group name="fade" tag="ol">
<li v-for="(item, index) in items"
v-bind:key="item + '_' + index" >
{{item}}
</li>
</transition-group>
Bug report (rejected)
I submitted this bug report to Vue.js devs here:
"Transition-group animates only last element if using index as the key"
https://github.com/vuejs/vue/issues/8718
It got closed instantly, so based on their input (requested I do a PR for comment, but that is not in my wheelhouse) I followed up with this feature request for the dev build to give an error, which would solve the problem at it's root.
Feature request (follow up, also rejected)
"Dev build console error when using index in :key value with v-for and transitions"
https://github.com/vuejs/vue/issues/8730
It seems reasonable to put a dev error on this issue, but the vue.js developers seem to think we should be able to figure this out on our own. I hope they come around and see this as a real issue. It's cost me hours of testing and reporting time to figure out.
I hope this helps other devs wasting time with this issue.
References
[1] https://github.com/vuejs/vue/issues/8718#issuecomment-416909724
My solution for this case:
create a random generated string for your array, then use this randomly generated string as the key.
template
<div v-for="(row, index) in rows" :key="row.randomKey">
...
</div>
script
export default {
data() {
return {
rows: [],
}
},
methods: {
add() {
this.rows.push({
id: null,
name: '',
randomKey: this.generateRandomKey()
})
},
remove(index) {
this.currency_exchange.splice(index, 1)
},
generateRandomKey() {
let length = 10
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
}
}
Megacromulent
Good research!
For those who, like me, came here looking for:
It is likely that the animation occurs when the key is changed i.e. When deleting and creating an element, if the key does not change, then there will be no animation.
When the array changes, all the elements are rebuilt, which means the keys are also rewritten, and if they change on the element, this will make the element go away and appear.
Megacromulent let's see:
In the second case, the option with index - we remove the first element of the array, new keys are placed over all the remaining elements in the component - but in the beginning they will be the same 0,1,2 ... i.e. The keys of the first list will not change and therefore the elements will not be destroyed and therefore will not be animated.
In the third version, the key for all elements will change every time, i.e. All elements will be redrawn i.e. Removed and rebuilt, animation will work for all elements
Well, in the first version. If the items are the same, it will be the same as with the index because the key will not change, which means, in the case of all the same, only the last one will be animated, i.e. When adding and removing items to the end of the list.

Scout Eclipse Neon margin on fields

Is it possible to set a margin around fields.
For example in image :
If I want to set lower (separated) checkBox in line with above once, is there a way to do it?
Marko
Start by inspecting the HTML code (with Chrome).
The code corresponding to the Checkbox Field is something like that:
<div class="form-field check-box-field"
data-modelclass="org.eclipse.scout.widgets.client.ui.forms.CheckboxFieldForm$MainBox$ConfigurationBox$CheckboxField"
data-classid="CheckboxField_org.eclipse.scout.widgets.client.ui.forms.CheckboxFieldForm"
id="scout.CheckBoxField[1-49]"
style="left: 0px; top: 14px; width: 1598px; height: 30px;"
>
<div class="field has-inner-alignment halign-left valign-top" style=
"left: 148px; top: 0px; width: 1420px; height: 30px;">
<div class="check-box" tabindex="0"></div>
<div class="label">
Checkbox
</div>
</div>
</div>
With CSS you can do anything possible:
.check-box-field {
background-color: red;
}
Now because you do not want to add some custom CSS style for all CheckBox Fields, you can define a custom Css-Class in your CheckBox:
#Order(4)
public class UnknownCheckBox extends AbstractBooleanField {
#Override
protected String getConfiguredCssClass() {
return "checkbox-under-listbox";
}
// ... Some Code ...
}
And now you add this CSS code:
.checkbox-under-listbox {
margin-left: 20px;
}
I have realized this example with the Widgets Demo Application (org.eclipse.scout.docs repository, releases/5.2.x branch). I added my css code in this file: org.eclipse.scout.widgets.ui.html/src/main/js/widgets/main.css (It is probably not the best approach to have everything in main.css).
You can deduce from this example how you can add an additional CSS/LESS module and macro to your application. This post: Inclusion of additional icons from font-awesome might also be usefull. You will have a main.css instead of a font.css.
WARNING: this is not state of the art.
At the end this is normal HTML development (single page application of course), so you can do what you want...
If you do not want to use the LESS compiler and the File preprocessor, you can simpelly add a normal CSS file in the folder:
<your_project>.ui.html/src/main/resources/WebContent
Let say:
<your_project>.ui.html/src/main/resources/WebContent/my_custom.css
Do not forget to include your CSS File between the <head> and </head> tags in the HTML index file:
<your_project>.ui.html/src/main/resources/WebContent/index.html
Something like:
<head>
<!-- some code -->
<link rel="stylesheet" type="text/css" href="my_custom.css">
<scout:stylesheet src="res/scout-module.css" />
<!-- some code -->
</head>
You can always use custom CSS: Let your field implement IStyleable and use setCssClass() to apply an appropriate CSS class. I'd try to avoid using such pixel pushing approaches as much as possible.

Changing listviewer format in App Inventor

I am trying to create an app with App Inventor which allows you to see files from a server and also download and share them.
I created 3 listviewers one that opens the file, the second allows to share it and the last allows you to download it. And It looks like this:
But I am looking to put all of this in the same column like this app do:
Does any one know what I have to do create a format like that?
Thanks.
Finally thanks to www.jquerymobile.com and some Taifun's tutorials I could create an interface similar to what I was looking for. I also achive how to recover he index selected by the user. Here I post the jquery code:
<!DOCTYPE html>
<html>
<head>
<title>0</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<style>
.split-custom-wrapper {
/* position wrapper on the right of the listitem */
position: absolute;
right: 0;
top: 0;
height: 100%;
}
.split-custom-button {
position: relative;
float: right; /* allow multiple links stacked on the right */
height: 100%;
margin:0;
min-width:3em;
/* remove boxshadow and border */
border:none;
moz-border-radius: 0;
webkit-border-radius: 0;
border-radius: 0;
moz-box-shadow: none;
webkit-box-shadow: none;
box-shadow: none;
}
.split-custom-button span.ui-btn-inner {
/* position icons in center of listitem*/
position: relative;
margin-top:50%;
margin-left:50%;
/* compensation for icon dimensions */
top:11px;
left:-12px;
height:40%; /* stay within boundaries of list item */
}
</style>
</head>
<body>
<div data-role="page">
<div data-role="content">
<div id="searchPickPlace">
<script>
// get the table to display from the window.AppInventor object and split at new line
var urlArray = window.AppInventor.getWebViewString().split("\n");
// split at comma
var doc = document;
var fragment = doc.createDocumentFragment();
document.write('<ul data-role="listview" data-filter="true">');
for(i=0;i<(urlArray.length-1);i++){
j = i + 1; //+1 because app invetor array start at position 1
var rowArray = urlArray[i].split(",");
html = '<li> \
<a id="R_'+j+'" onClick="reply_click(this.id)" href="#">\
<h3>'+rowArray[1]+" "+j+'</h3>\
<p>description</p>\
</a>\
<div class="split-custom-wrapper">\
<a id="D_'+j+'" onClick="reply_click(this.id)" href="#" data-role="button" class="split-custom-button" data-icon="arrow-d" data-rel="dialog" data-theme="c" data-iconpos="notext"></a>\
<a id="S_'+j+'" onClick="reply_click(this.id)" href="#" data-role="button" class="split-custom-button" data-icon="gear" data-rel="dialog" data-theme="c" data-iconpos="notext"></a>\
</div>\
</li>';
document.write(html);
}
document.write('</ul>');
function reply_click(clicked_id)
{
//alert(clicked_id);
window.document.title = clicked_id;
setTimeout(function(){window.document.title = "0";}, 500);
}
</script>
</div>
</div><!-- content -->
</div><!-- /page -->
</body>
</html>
With this code I get this interface:
When you click a button the text label change to the number of the index you have clicked with a prefix depending if you have clicked the main area or the other buttons. The text label only change during less than a secon so if during this time you click again the interface wont recive the click. I think this is work perfect for what I want to do becaus I don't want any one that spam the button but If want an app where you can spam a button you will have to figure it out an other solution.
To do that you will need a clock. In thsi example I have obtained the table from my web site but you can create your own table with a text variable separeting the columns by comas and each line by "\n". I post the app invetor blocks down here:
I am aware that maybe there is a better solution if any one can find it out, I am open to listen new sugestions.
Thanks

Resources