Got duplicate table when export handsontable to XLS - handsontable

I was to export a handsontable to XLS file but i encountered this bug:
The result excel file contains 2 table like this:
First name Last name Email Phone Password
23123 31231231 213#dsfsd213.563 NjU0NTY0 46565465546
Buu Mr your#email.com MTI0NTU1 your password
First name Last name Email Phone Password
In the code box below is my code in jsp
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<script src="resources/handsontable/handsontable.full.js"></script>
<link rel="stylesheet" media="screen" href="resources/handsontable/handsontable.full.css">
<link rel="stylesheet" media="screen" href="resources/handsontable/github.css">
<div class="tab-pane active" id="user">
<!-- <form action="addBatchUser" method="POST"> -->
<div class="col-lg-12">
<div class="page-header">
<h4>
<span>Export to Excel</span>
</h4>
</div>
<div class="panel-body">
<div class="form-group">
<label class="col-lg-2 control-label">Parent Group</label>
<div class="col-lg-10">
<input type="text" readonly id="parentGroupUser" class="form-control uniform-input text focus"></input> <input
type="hidden" id="group-parent" name="groupou"></input>
</div>
</div>
<br />
<div class="form-group">
<!-- Space line -->
<div class="col-lg-12">
<div class="col-lg-2">
<label class="control-label"></label>
</div>
<div class="col-lg-10"></div>
</div>
<div class="col-lg-2">
<label class="control-label"></label>
</div>
<div class="col-lg-10">
<div id="example"></div>
<br /> <input type="button" value="Export" id="btnExport" class="btn btn-success" />
<div>
<img id="access_log_print" src="resources/images/ajax-loader.gif" />
</div>
</div>
</div>
</div>
</div>
<!-- </form> -->
</div>
<div id="resViewer"></div>
<script language="JavaScript" type="text/javascript">
$(document).ready(
function() {
$("#btnExport").click(
function(e) {
window.open('data:application/vnd.ms-excel,'
+ encodeURIComponent($('div[id$=example]')
.html()));
e.preventDefault();
});
});
$(document).ready(
function() {
hideLoadingMsg();
function showLoadingMsg() {
$("input[type=submit]").attr("disabled", "disabled");
$('#access_log_print').show();
}
function hideLoadingMsg() {
$("input[type=submit]").removeAttr("disabled");
$('#access_log_print').hide();
}
var data = ${listuser}
;
var container = document.getElementById('example');
var hot = new Handsontable(container, {
data : data,
rowHeaders : false,
colHeaders : true,
// contextMenu : true,
colHeaders : [ 'First name', 'Last name', 'Email', 'Phone',
'Password' ],
colWidths : [ 130, 130, 150, 120, 130 ],
columns : [ {
data : "firstName",
readOnly : true
}, {
data : "lastName",
readOnly : true
}, {
data : "email",
readOnly : true
}, {
data : "telNumber",
readOnly : true
}, {
data : "password",
readOnly : true
} ]
});
// var hot ={}
// $("#save")
// .click(
// function() {
// var json = container
// .handsontable('getData');
// var jsonData = createJsonSection(json);
// if (jsonData === null) {
// return false;
// } else {
// showLoadingMsg();
// var dataJson = JSON
// .stringify(jsonData);
// console.log(dataJson);
// $
// .ajax({
// url : "addBatchUser",
// data : {
// "data" : dataJson,
// "groupou" : $(
// '#group-parent')
// .val(),
// "saveToLdap" : $(
// '#saveToLdap')
// .is(
// ':checked'),
// "saveToSvnAcm" : $(
// '#saveToSvnAcm')
// .is(
// ':checked'),
// "svnAcmGroup" : $(
// '#svnAcmGroup')
// .val()
// }, //returns all cells' data
// type : "POST",
// success : function(
// res) {
// $("#resViewer")
// .empty();
// $("#resViewer")
// .append(
// res);
// hideLoadingMsg();
// }
// });
// }
// });
});
</script>

I recommend you don't export to CSV using the html content of the table you see but rather use the data itself to parse and export correctly. The problem with your method is that Handsontable is rendering a floating "headers" row used to display the header at the bottom. If you still want to use this method, you could simply parse this html and remove the last line.

Related

How get quill and other form to JS submit function?

I wanna use quill rich editor and other fields on my form. But cant get access to quill innerHTML from JS function. I am using Laravel with Alpinejs and my code is
<form x-data="contactForm()" #submit.prevent="submit">
<div class="col-12">
<div class="mt-2 w-100 bg-white" wire:ignore>
<div
x-data
x-ref="quillEditor"
x-init="
quill = new Quill($refs.quillEditor, {
theme: 'snow',
modules: {toolbar: '#toolbar'}
});
quill.on('text-change', function () {
$dispatch('input', quill.root.innerHTML);
});"
wire:model.debounce.2000ms="description"
class="sign__textarea"
style="height: 300px;"
>{{ old('description', $services_users->description) }}
</div>
</div>
</div>
<div class="col-12">
<input name="message" x-model="data.title">
</div>
<div class="col-12 col-xl-3 mt-5">
<button type="submit" x-text="buttonText" :disabled="loading"></button>
</div>
</form>
<script>
function contactForm() {
return {
data: {
title: "",
myQuill: quill.root.innerHTML,
},
buttonText: "Save",
loading: false,
submit() {
this.buttonText = "Saving...";
this.loading = true;
fetch('myurl.endpoint', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify(this.data),
}).then(() => {
alert("Form submitted");
}).catch(() => {
alert("Something went wrong");
}).finally(() => {
this.data.title = ""
this.buttonText = "Save";
this.loading = false;
});
},
};
}
</scirpt>
Now i have an error Can't find variable: quill how can i get all fields from form and send to backend event if quill is not a form field?
It doesn't work because you're calling the variable "quill" in the parent and you're declaring it in the child. To fix it declare the x-init directive in the form.
listening to the "text-change" event is not necessary. A good option is to add the content of the container before submitting the form.
see : https://alpinejs.dev/directives/data#scope
<form x-data="contactForm()" x-init="
quill = new Quill($refs.quillEditor, {
theme: 'snow'
});
quill.on('text-change', function () {
$dispatch('input', quill.root.innerHTML);
});" #submit.prevent="submit">
<div class="col-12">
<div class="mt-2 w-100 bg-white" wire:ignore>
<div
x-ref="quillEditor"
wire:model.debounce.2000ms="description"
class="sign__textarea"
style="height: 300px;"
>{{ old('description', $services_users->description) }}
</div>
</div>
</div>
<div class="col-12">
<input name="message" x-model="data.title">
</div>
<div class="col-12 col-xl-3 mt-5">
<button type="submit" x-text="buttonText" :disabled="loading"></button>
</div>
</form>
<script>
function contactForm() {
return {
quill:null,
data: {
title: "",
// myQuill: function(){ return this.quill.root.innerHTML}
},
buttonText: "Save",
loading: false,
submit() {
this.buttonText = "Saving...";
//add content quill here
this.data.myQuill = this.quill.root.innerHTML;
this.loading = true;
fetch('myurl.endpoint', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify(this.data),
}).then(() => {
alert("Form submitted");
}).catch(() => {
alert("Something went wrong");
}).finally(() => {
this.data.title = ""
this.buttonText = "Save";
this.loading = false;
});
},
};
}
</script>
Ok this is what i did
<form x-data="contactForm()" x-init="initQuill()" x-on:submit="submit()" method="POST" action="target.url">
<div x-ref="editor"></div>
<input x-ref="editorValue" type="hidden" name="hidden_input">
<button>Save</button>
</form>
<script>
function contactForm(){
return {
initQuill(){
new Quill(this.$refs. editor, {theme: 'snow'});
},
submit(){
console.log(this.$refs. editor.__quill.root.innerHTML);
this.$refs.editorValue.value = this.$refs.editor.__quill.root.innerHTML;
}
}
}
</script>
Now is ok and works with basic. You can extend function with new features etc. Thx for help guys.

How to calculate two input values and put the result in another variable?

I have Button A and Button B, When these buttons get clicked I'm getting
two input boxes with some value I want to store a total of these two input boxes and also want their label gets created dynamically
<template>
<div> <form type="get" action="/asd">
<div>
<label>Add A</label>
<button type="button" #click="addRow">100</button>
</div>
<div> <label>Add B</label>
<button type="button" #click="addRow1">200</button>
</div>
<div v-for="row in rows" :key="row.id">
<button-counter :name ="row.name" :id="row.id" :value="row.value"></button-counter>
</div> <div>total = ?</div>
<button>submit</button>
</form>
</div>
<script type="text/javascript">
Vue.component("button-counter", {
props: {
value: {
default: ""
}
},
template: '<input name=row.name type="text" style="margin-top: 10px;" v-model="value" >'
});
export default {
data() {
return {
rows: [],
count: 0
};
},
methods: {
addRow: function() {
var txtCount = 1;
let id = "txt_" + txtCount;
this.rows.push({ name:'A',value:100, description: "textbox1", id });
},
addRow1: function() {
var txtCount = 1;
let id = "txt2_" + txtCount;
this.rows.push({name:'B',value:200, description: "textbox2", id });
}
}
};

Upload Image in Vue Component with Laravel

I am making a simple website that has a feature to upload images. I tried it Laravel way which I made it in blade template and it works fine. Now I am trying to make it inside Vue Components
Here's my Create.vue
<template>
<div>
<div class="row">
<input type="hidden" name="_token" :value="csrf">
<div class="col-md-5">
<div class="detail-container">
<label for="title">Book Title:</label>
<input type="text" name="title" id="title" v-model="book_title" class="form-control">
</div>
<div class="detail-container">
<label for="title">Book Description:</label>
<textarea type="text" name="description" id="description" v-model="book_description" class="form-control" rows="5"></textarea>
</div>
<div class="detail-container">
<label for="title">Tags:</label>
<multiselect v-model="tags" :show-labels="false" name="selected_tags" :hide-selected="true" tag-placeholder="Add this as new tag" placeholder="Search or add a tag" label="name" track-by="id" :options="tagsObject" :multiple="true" :taggable="true" #tag="addTag" #input="selectTags">
<template slot="selection" slot-scope="tags"></template>
</multiselect>
</div>
</div>
<div class="col-md-7">
<!-- BOOK COVER WILL GO HERE -->
<div class="detail-container">
<label>Book Cover:</label>
<input type="file" class="form-control-file" id="book_cover" name="selected_cover" #change="onFileChange">
<small id="fileHelp" class="form-text text-muted">After you select your desired cover, it will show the preview of the photo below.</small>
<div id="preview">
<img v-if="url" :src="url" height="281" width="180" />
</div>
</div>
</div>
<div class="detail-container" style="margin-top: 20px;">
<button class="btn btn-primary" #click="saveBook()">Next</button>
</div>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
// register globally
Vue.component('multiselect', Multiselect)
export default {
// OR register locally
components: { Multiselect },
data () {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
url: null,
selected_cover: null,
tags: [],
tagsObject: [],
selected_tags: [],
book_title: '',
book_description: ''
}
},
methods: {
getTags() {
let vm = this;
axios.get('/admin/getTags').then(function(result){
let data = result.data;
for(let i in data) {
vm.tagsObject.push({id: data[i].id, name: data[i].name});
}
});
},
addTag (newTag) {
const tag = {
name: newTag,
id: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.tagsObject.push(tag);
this.tags.push(tag);
},
selectTags(value) {
this.selected_tags = value.map(a=>a.id);
},
onFileChange(e) {
const file = e.target.files[0];
this.url = URL.createObjectURL(file);
this.selected_cover = file;
},
saveBook() {
const fd = new FormData();
fd.append('image', this.selected_cover, this.selected_cover.name)
console.log(this.selected_cover);
var book_details = {
'title': this.book_title,
'description': this.book_description,
'book_cover': this.selected_cover,
'tags': this.selected_tags
};
axios.post('/admin/saveBook', book_details).then(function(result){
console.log('done')
})
}
},
created() {
this.getTags();
}
}
</script>
<!-- New step!
Add Multiselect CSS. Can be added as a static asset or inside a component. -->
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
and here's my controller
public function store(Request $request)
{
$this->validate(request(), [
'title' => 'required|min:5',
'description' => 'required|min:10',
'book_cover' => 'required|image|mimes:jpeg,jpg,png|max:10000'
]);
// File Upload
if($request->hasFile('book_cover')) {
$fileNameWithExt = $request->file('book_cover')->getClientOriginalName();
// GET FILE NAME
$filename = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
// GET EXTENSION
$extension = $request->file('book_cover')->getClientOriginalExtension();
// File Unique Name
$fileNameToStore = $filename. '_'. time().'.'.$extension;
$path = $request->file('book_cover')->storeAs('public/book_covers', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$book = new Book;
$book->title = request('title');
$book->description = request('description');
$book->book_cover = $fileNameToStore;
$book->save();
$book->tags()->sync($request->tags, false);
return back()->with('success', 'Book Created Successfully!');
}
I never touched my controller because this is what I used when I do this feature in Laravel Way but when I save it, the details are being saved but the image is not uploading instead it saves noimage.jpg in the database. Does anyone know what I am doing wrong?
i tried to add this part const fd = new FormData(); in book_details but when i console.log(fd) it returned no data.
you should pass the fd object and not the book_details in your POST request.
you could do it something like this.
onFileChange(e) {
const file = e.target.files[0];
// this.url = URL.createObjectURL(file);
this.selected_cover = file;
},
saveBook() {
const fd = new FormData();
fd.append('image', this.selected_cover)
fd.append('title', this.book_title)
fd.append('description', this.book_description)
fd.append('book_cover', URL.createObjectURL(this.selected_cover))
fd.append('tags', this.selected_tags)
axios.post('/admin/saveBook', fd).then(function(result){
console.log('done')
})
}
and also, you can't just console.log the fd in the console. what you can do instead is something like this
for (var pair of fd.entries()) {
console.log(pair[0]+ ', ' + pair[1]);
}
FormData is a special type of object which is not stringifyable and cannot just be printed out using console.log. (link)

How to use ng-if in Select with multiple conditions-AngularJS

I am new to angularjs. I'm trying to write code to get content from multiple select options. As per my below code, I want to get #html content when I select "HTML 5 FEATURES" from Product drop down.How can I get in simpler way. Here is what my Code looks like:
enter code here
<html>
<head>
<link rel="stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/
css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/
angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="container">
<h1>Web Developer</h1>
<div class="row">
<div class="col col-lg-4">
<form class="form">
<div class="form-group">
<label> Categories :</label>
<select name="categoriesList" ng-model="selectedCategory"
class="form-control">
<option ng-repeat="item in CategoryList"
value='{{item}}'>{{item.value}}</option>
</select>
</div>
<div class="form-group">
<label> Products :</label>
<select ng-disabled="selectedCategory == null"
name="productList" ng-model="selectedProduct"
class="form- control">
<option ng-repeat="item in ProductList | myFilter :
selectedCategory" value='{{item}}'>{{item.value}}</option>
</select>
</div>
<div id="html" ng-if="selectedProduct.value === 'HTML 5 FEATURES'">
<div class="newFeatures">
<ul>
<li>New Doctype</li>
<li>The Figure Element</li>
<li>Email Inputs</li>
<li>Placeholders</li>
<li>Local Storage</li>
<li>Autofocus Attribute</li>
</ul>
</div>
</div>
</form>
</div>
</div>
<script>
var app = angular.module('myApp', []);
angular.module('myApp').filter('myFilter', function() {
return function(input, selectedCategory) {
input = input || '';
if(selectedCategory == null){
return input;
}else{
var out = new Array();
selectedCategory = JSON.parse(selectedCategory);
for (var i = 0; i < input.length; i++) {
var item = input[i];
if(item.categoryId == selectedCategory.id){
out.push(item);
}
}
return out;
}
};
});
app.controller('myCtrl', ['$scope', function($scope) {
$scope.selectedCategory = null;
$scope.selectedProduct = null;
$scope.CategoryList = [
{id:0, value:'HTML'},
{id:1, value:'CSS'},
{id:2, value:'JAVA SCRIPT'},
{id:3, value:'ANGULAR JS'}
];
$scope.ProductList = [
{categoryId:0, id:1, value:'HTML 5 FEATURES'},
{categoryId:0, id:2, value:'WEB WORKERS'},
{categoryId:0, id:3, value:'STORAGE'},
{categoryId:0, id:3, value:'CANVAS'},
{categoryId:0, id:3, value:'KEYFRAMES'},
{categoryId:1, id:4, value:'BOX MODEL'},
{categoryId:1, id:5, value:'NEW CSS3 FEATURES'},
{categoryId:1, id:6, value:'POSITIONS'},
{categoryId:2, id:7, value:"OOPs"},
{categoryId:2, id:8, value:'ARRAY MANIPULATIONS'},
{categoryId:2, id:9, value:'EMAIL'},
{categoryId:3, id:9, value:'DIRECTIVES'},
{categoryId:3, id:9, value:'FILTERS'},
{categoryId:3, id:9, value:'SCOPES & ROOT SCOPES'},
];
}]);
</script>
</body>
</html>
Simple way - for example put $http.get request into you controller and set ProductList data.
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
$scope.ProductList = response.data;
}, function errorCallback(response) {
});

Refreshing Kendo UI viewModel

I have a very simply page at the moment. It has a first name input, last name input, and a list of names added. You can add your first and last name to the text box, press add. It adds it the peopleList I have and adds a new listItem with their name.
My issue is when I add to the peopleList in my code, it does not update the listView. I think I need to use observable, but I am not exactly sure how to do it. My list shows it has 25 items added to it after I click btnMany, which is how many it show have.
here is the body of my code:
<!--Load Some Data-->
<div id="peopleDefaultView"
data-role="view"
data-model="ViewModel"
data-layout="default">
<!--View-->
<input type="text" data-bind="value: firstName" id="fName" />
<input type="text" data-bind="value: lastName" id="lName" />
<a data-bind="click: addName" data-role="button" id="btnOne">Add</a>
<a data-bind="click: setValues" data-role="button" id="btnMany">Add Many</a>
<div style="margin-top: 10px">
People List:
<ul data-template="people-l-template" data-bind="source: peopleList" id="pList"></ul>
</div>
</div>
<!-- Kendo Template-->
<script id="people-l-template" type="text/x-kendo-template">
<li>
FirstName: <span data-bind="text: first"></span>
LastName: <span data-bind="text: last"></span>
<a data-bind="click: removeName" data-role="button" id="btnRemoveName">X</a>
</li>
</script>
And here is my script to go along with it
<script>
var ViewModel = {
firstName: '',
lastName: '',
peopleList: [],
addName: function (e) {
this.get("peopleList").push({
first: this.get("firstName"),
last: this.get("lastName"),
});
this.set("firstName", '');
this.set("lastName", '');
},
removeName: function (e) {
this.set("peopleList", jQuery.grep(this.peopleList, function (item, i) {
return (item.firstName != e.data.firstName && item.lastName != e.data.lastName);
}));
},
setValues: function (e) {
GetValueFromServer();
}
};
var GetValueFromServer = function () {
$.ajax({
type: "GET",
url: "GetPeopleService.svc/GetPersonById/",
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
response.forEach(function (person) {
ViewModel["peopleList"].push({
first: person.firstName,
last: person.lastName
});
});
alert(ViewModel.peopleList.length);
},
error: function (response) {
console.log(response);
}
});
};
var application = new kendo.mobile.Application(document.body);
</script>
There were a few things wrong with the code you provided, the most notably being that you didn't set the role for your <ul> element. You need to change it to have the attribute data-role="listview". You also can't use an <li> element as the root element for a listview template (KendoUI automatically takes care of this for you), otherwise you'll get an error when the list is bound.
Here's an example on JS Bin.
And here's the code:
<!--Load Some Data-->
<div id="peopleDefaultView"
data-role="view"
data-model="viewModel"
data-layout="flat">
<!--View-->
<input type="text" data-bind="value: firstName" id="fName" />
<input type="text" data-bind="value: lastName" id="lName" />
<a data-bind="click: addName" data-role="button" id="btnOne">Add</a>
<div style="margin-top: 10px">
People List:
<ul id="pList"
data-role="listview"
data-template="people-l-template"
data-bind="source: peopleList">
</ul>
</div>
</div>
<!-- Kendo Template-->
<script id="people-l-template" type="text/x-kendo-template">
FirstName: <span>#:first#</span>
LastName: <span>#:last#</span>
<a id="btnRemoveName"
data-role="button"
data-bind="click: removeName"
data-first="#:first#" data-last="#:last#">
X
</a>
</script>
...
var viewModel = {
firstName: null,
lastName: null,
peopleList: [],
addName: function (e) {
var me = this;
me.get('peopleList').push({
first: me.get('firstName'),
last: me.get('lastName')
});
me.set('firstName', '');
me.set('lastName', '');
},
removeName: function (e) {
var me = this;
me.set('peopleList', $.grep(me.peopleList, function (item, i) {
return item.first != e.target.data('first')
&& item.last != e.target.data('last');
}));
}
};
var application = new kendo.mobile.Application(document.body);

Resources