Line break in vue js - vue.js

Vue js code:-
getTitleText(){
let mainTitle = "";
let getTitle = this.titleText;
let countGetTitle = getTitle.split(" ").length;
if(countGetTitle > 4){
mainTitle = getTitle.replace(/(\S+\s*){1,4}/g, "$&\n");
}
console.log("countGetTitle = ",countGetTitle);
console.log("getTitle = ",mainTitle);
return mainTitle;
},
html:-
<div class="end-workout-title1">{{ getTitleText() }}</div>
but I am getting a full line in output. Please help me where I am getting worng

Add to your class add the white-space:pre rule :
.end-workout-title1{
...
white-space:pre
}

Related

Update v-html without misbehaving focus on typing VUE JS

I need help,
Requirement
when the user types in an input box I want to highlight the link with blue color if any
My Research
when I dig into it, I realize that without using a contenteditable div it's not possible to do, also there is no v-model associated with contenteditable div I am manually updating the state.
so far I have this, courtesy- contenteditable div append a html element and v-model it in Vuejs
<div id="app"><div class="flex">
<div class="message" #input="updateHtml" v-html="html" contenteditable="true"></div>
<br>
<div class="message">{{ html }}</div>
</div>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
html: 'some text',
},
methods: {
updateHtml: function(e) {
this.html = e.target.innerHTML;
},
renderHtml: function(){
this.html += '<img src="https://cdn-images-1.medium.com/max/853/1*FH12a2fX61aHOn39pff9vA.jpeg" alt="" width=200px>';
}
}
});</script>
Issue
every time user types something, the focus is misbehaving which is strange to me, I want v-html to update along with user types #keyup,#keydown also have the same behavior.it works ok on #blur #focusout events, but that's not what I want
Appreciate Help.Thanks
I figured it out myself. Posting the answer so that may help other developers. v-HTML doesn't do all the trick. You’ll need to store the cursor position so it can be restored properly each time the content updates as well as parse the content so that it renders as expected. Here is the example
HTML
<p>
An example of live syntax highlighting in a content-editable element. The hard part is storing and restoring selection after changing the DOM to account for highlighting.
<p>
<div contentEditable='true' id='editor'>
Edit text here. Try some words like bold and red
</div>
<p>
Just a demo trivial syntax highlighter, should work with any syntax highlighting you want to implement.
</p>
JS
const editor = document.getElementById('editor');
const selectionOutput = document.getElementById('selection');
function getTextSegments(element) {
const textSegments = [];
Array.from(element.childNodes).forEach((node) => {
switch(node.nodeType) {
case Node.TEXT_NODE:
textSegments.push({text: node.nodeValue, node});
break;
case Node.ELEMENT_NODE:
textSegments.splice(textSegments.length, 0, ...(getTextSegments(node)));
break;
default:
throw new Error(`Unexpected node type: ${node.nodeType}`);
}
});
return textSegments;
}
editor.addEventListener('input', updateEditor);
function updateEditor() {
const sel = window.getSelection();
const textSegments = getTextSegments(editor);
const textContent = textSegments.map(({text}) => text).join('');
let anchorIndex = null;
let focusIndex = null;
let currentIndex = 0;
textSegments.forEach(({text, node}) => {
if (node === sel.anchorNode) {
anchorIndex = currentIndex + sel.anchorOffset;
}
if (node === sel.focusNode) {
focusIndex = currentIndex + sel.focusOffset;
}
currentIndex += text.length;
});
editor.innerHTML = renderText(textContent);
restoreSelection(anchorIndex, focusIndex);
}
function restoreSelection(absoluteAnchorIndex, absoluteFocusIndex) {
const sel = window.getSelection();
const textSegments = getTextSegments(editor);
let anchorNode = editor;
let anchorIndex = 0;
let focusNode = editor;
let focusIndex = 0;
let currentIndex = 0;
textSegments.forEach(({text, node}) => {
const startIndexOfNode = currentIndex;
const endIndexOfNode = startIndexOfNode + text.length;
if (startIndexOfNode <= absoluteAnchorIndex && absoluteAnchorIndex <= endIndexOfNode) {
anchorNode = node;
anchorIndex = absoluteAnchorIndex - startIndexOfNode;
}
if (startIndexOfNode <= absoluteFocusIndex && absoluteFocusIndex <= endIndexOfNode) {
focusNode = node;
focusIndex = absoluteFocusIndex - startIndexOfNode;
}
currentIndex += text.length;
});
sel.setBaseAndExtent(anchorNode,anchorIndex,focusNode,focusIndex);
}
function renderText(text) {
const words = text.split(/(\s+)/);
const output = words.map((word) => {
if (word === 'bold') {
return `<strong>${word}</strong>`;
}
else if (word === 'red') {
return `<span style='color:red'>${word}</span>`;
}
else {
return word;
}
})
return output.join('');
}
updateEditor();
Hope this helps...

Vue.js reference error (event.target) not defined

I have a vue component that has different methods, f.ex. mouseMove:
mouseMove: function(event) {
console.log("Event is: " + event);
element5 = event.target
this.elementMove = element5
if (element5.getAttribute('data') == 'day') {
hourPreStart = parseInt(element5.getAttribute('value'))
dayPreStart = parseInt(element5.parentElement.firstChild.getAttribute('day-value'));
this.hourPreEnd = hourPreStart
this.dayPreEnd = dayPreStart
}
console.log(this.hourPreStart, this.dayPreStart, this.hourPreEnd, this.dayPreEnd)
},
When I hover over a field with my mouse I get this error:
I don't know what the problem is because event is defined.
Here's the full component.
Can someone help me?
You are using this code:
<tbody #mousedown='mouseDown' #mouseup='mouseUp' #mousemove='mouseMove'>
But you should add $event to handlers like this:
<tbody #mousemove='mouseMove($event)'>
event5 is not defined (as the error stares). You have to first define event5 to use it.
Use this
mouseMove: function(event) {
console.log("Event is: " + event);
let element5 = event.target
this.elementMove = element5
if (element5.getAttribute('data') == 'day') {
let hourPreStart = parseInt(element5.getAttribute('value'))
let dayPreStart = parseInt(element5.parentElement.firstChild.getAttribute('day-value'));
this.hourPreEnd = hourPreStart
this.dayPreEnd = dayPreStart
}
console.log(this.hourPreStart, this.dayPreStart, this.hourPreEnd, this.dayPreEnd)
}

I cannot integrate js query file in vue

i would like to use a js query code that I found on codepen in my vue project, but im not sure How to integrate it .
I simply pasted the file in my created() of my vue component but it doesn seem to work out.. the code is supposing to run a visual animation when typing chinese caractere in the input form.
this is the codepen : https://codepen.io/simeydotme/pen/CFcke
var $input = $('input');
$input.on({
"focus": function(e) {
$(".input-container").addClass("active");
},
"blur": function(e) {
$(".input-container").removeClass("active");
}
});
var previous = null;
setInterval( function() {
if( previous !== $input.val()
|| "" === $input.val()) {
getGoodCharacters( $input );
previous = $input.val();
}
}, 500);
function getGoodCharacters( $this ) {
var output = $this.val().trim();
var letters = output.split("");
var url = "https://service.goodcharacters.com/images/han/$$$.gif";
$(".error-container, .help").removeClass("show");
$(".output-container").empty();
for( letter in letters ) {
var img = letters[letter] + "";
var newurl = url.replace("$$$",img);
loadCharacter( newurl , img );
}
}
function loadCharacter( url , letter ) {
var img = new Image();
var $output = $(".output-container");
var $a = $("<a/>");
var l = $("input").val().length;
var cwidth = "120px";
if( l > 7 ) { cwidth = "70px"; }
else if( l > 6 ) { cwidth = "90px"; }
else if( l > 5 ) { cwidth = "100px"; }
$(img).load(function(){
$a.attr({
"href": url,
"title": "Good Character Chinese Symbol: "+ letter + ""
}).css("width", cwidth ).append( $(this) ).appendTo($output);
$(".help").addClass("show");
}).attr({
src: url
}).error(function(){
$(".error-container").addClass("show");
});
}
var $try = $(".tryme a").on("click", function(e) {
e.preventDefault();
$input.val( $(this).text() );
});
I also imported the jquery module in my componant
import $ from "jquery";
here is the html that i added in the template
<div class="container input-container">
<input type="text" id="input" placeholder="中文" value="中文"/>
</div>
Thanks!

ngIf on div containing dynamically generated compoent

I have a dynamically generated component which generates on run time. following is the .ts file
`#ViewChild(TermsheetDirective) termHost: TermsheetDirective;
#Input() term;
#Input() title = '';
#Input() Qnumber = '';
#Output() result = new EventEmitter<any>();
section_title = '';
number = '';
component = [];
show = false;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
}
ngOnInit() {
this.number = this.Qnumber;
this.section_title = this.title;
}
ngAfterViewInit() {
}
ngAfterContentInit() {
}
loadcomponents() {
console.log(this.termHost);
for (let j = 0; j < this.term.components.length; j++) {
let termItem = this.term.components[j];
let componentFactory = this.componentFactoryResolver.resolveComponentFactory(termItem.component);
let viewContainerRef = this.termHost.viewContainerRef;
let componentRef = viewContainerRef.createComponent(componentFactory);
(<TermComponent>componentRef.instance).data = termItem.data;
this.component[j] = componentRef;
}
}
getdata() {
let output = [];
for (let i = 0; i < this.component.length; i++) {
let temp = {
slug : this.section_title,
type : this.component[i].type,
value : this.component[i]._component.getdata()
};
output[i] = temp;
}
this.result.emit(output);
return output;
}
showcomp() {
console.log("In if");
this.show = true;
this.loadcomponents();
}
hidecomp() {
this.show = false;
}`
and following is my html
`<div class="main">
<div class="div_for_ques">
<div class="question">
<div class="number">
{{number}}
</div>
<div class="textbox">
{{section_title}}
</div>
<div class="arrow" *ngIf="!show">
<a (click)="showcomp()" class="glyphicon"></a>
</div>
<div class="arrow" *ngIf="show">
<a (click)="hidecomp()" class="glyphicon"></a>
</div>
</div>
<div class="sec_two" *ngIf="show">
<ng-template term-host></ng-template>
</div>
</div>
</div>`
I want the div that contains the dynamically generated component to appear only when a certain button is clicked. but i am having following response.
But when I try to show this div without ngIf it is working fine. But with ngIf termHost is undefined! Can someone please explain what is happening here!
Well, you are trying to reference to viewContainerRef before change detection cycle has completed, that is why you get that error.
There is more than one solution to this, you can use a setter for the ViewChild, that will be called once after the *ngIf becomes true
e.g
#ViewChild('') set content(x:x) {
this.x = x;
}
OR you can inject the change detector manually
constructor(private changeDetector : ChangeDetectorRef) {}
You can then call it after you click your button
this.changeDetector.detectChanges();
OR You can also use a QueryList to achieve the same effect because you can subscribe to changes
Please apply these techniques to your logic to solve your problem

Change avatar with vue.js without refresh?

I have this in view:
<div class="seller_image" :style="{background: 'url(' + user_credentials.avatar +')', backgroundSize: 'cover ', display: 'block'}">
</div>
In vue i have this:
setAvatar:function(x,y,w,h){
this.setAvatarLoader = true;
var data = new FormData();
this.x1 = $('#x1').val();
this.y1 = $('#y1').val();
this.w = $('#w').val();
this.h = $('#h').val();
this.x2 = $('#x2').val();
this.y2 = $('#y2').val();
data.append('avatar',this.$els.fileAvatarImage.files[0]);
data.append('x1',this.x1);
data.append('x2',this.x2);
data.append('y1',this.y1);
data.append('y2',this.y2);
data.append('w',this.w);
data.append('h',this.h);
user_id = this.user_credentials.user_id;
this.$http.post('/profile/' + user_id + '/basic_info/set_avatar',data).then(function(response){
this.avatarImageSet = false;
public_path = response.data.public_path;
url_path = response.data.url_path;
filename = response.data.filename;
this.setAvatarLoader = false;
this.basic_status = true;
this.basic_success_message = response.data.successMsg;
this.profile_image = url_path;
this.user_credentials.avatar = url_path
this.getAvatar();
$("html, body").animate({ scrollTop: 0 }, "slow");
}, function(response) {
this.setAvatarLoader = false;
$('#myModal').modal('hide');
this.getAvatar();
console.log('error');
});
},
When I refresh the page I get the avatar but in time when I set it it does not change the image.
Any suggestion?
As #AWolf said, it's difficult to guess what's the problem with your code because I can see only a part of your code base.
Another possible issue could be the url_path. If it remains the same, will never change. So, you need to append the timestamp:
this.user_credentials.avatar = url_path + '?' + Date.now()
https://jsfiddle.net/pespantelis/fy0re26m/
As mentioned in the comments, try to avoid jQuery because it's most of the time not needed and it is making things more complicated.
Please have a look at the demo below for a simple image uploader/avatar changer or at this fiddle.
The demo just opens a file picker dialog and then the returned file is used to update the displayed image. (Posting to server is not added in the demo.)
To your code:
Something like $('#x1').val() shouldn't be done with Vue.js because in Vue you're doing that model driven.
So the only source of truth is your data model and not the stuff displayed in the DOM.
Not sure what you're trying to do with the x1,y1, ... code. That's not clear from your snippet with-out the html markup.
new Vue({
el: '#app',
data() {
return {
user_credentials: {
avatar: 'https://unsplash.it/100/100'
}
}
},
methods: {
changeAvatar() {
const input = document.createElement('input');
let self = this;
input.setAttribute("type", "file");
input.addEventListener('change', function(e) {
// uploading code from this fiddle: http://jsfiddle.net/vacidesign/ja0tyj0f/
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
// image is loaded callback
self.user_credentials.avatar = e.target.result;
// here you can post the data to your backend...
};
reader.readAsDataURL(this.files[0]);
}
})
input.click(); // opening dialog
return false; // avoiding navigation
}
}
})
.seller_image {
width: 200px;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<div id="app">
<div class="seller_image" :style="{background: 'url(' + user_credentials.avatar +')', backgroundSize: 'cover ', display: 'block'}">
</div>
<button #click="changeAvatar()">
Change
</button>
</div>