I'm working on polymer based front-end project. I'm pretty new at this kind of stuff and I'm struggling finding info and working examples of components I need. I know there is demo showcases of those components but they don't give me what I need.
<iron-form id="formForm">
<form>
<paper-autocomplete label="Country" required error-message="This field is required"></paper-autocomplete>
</form>
</iron-form>
When I use paper-autocomplete element inside <iron-form>, and add required attribute to it, <iron-form> calls paper-autocomplete validator. But when I create my own polymer element which has only paper-autocomplete included, iron form doesn't see it when I include it inside.
There is my custom polymer element
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../../bower_components/paper-autocomplete/paper-autocomplete.html">
<link rel="import" href="../globals-behavior.html">
<dom-module id="autocomplete-country">
<template>
<iron-ajax id="countryFindCall"
url="{{restUri}}/classifier/country/find"
params="{{query}}"
on-response="handleResponse"
debounce-duration="300"></iron-ajax>
<paper-autocomplete label="Country" id="country-autocomplete" remote-source="true" min-length="2"
text-property="label" value-property="value" disable-show-clear="true"></paper-autocomplete>
</template>
<script>
Polymer({
is: "autocomplete-country",
behaviors: [
GlobalsBehavior
],
properties: {
item: {
notify: true
},
query: {
type: Object
},
result: {
type: Object
},
selected: {
type: Object,
value: {}
}
},
attached: function() {...},
handleResponse: function (data) {...},
onSelect: function(event) {...},
onChange: function(event) {...},
onBlur: function() {...}
});
</script>
</dom-module>
And this is how I'm including it
<iron-form id="formForm">
<form>
<autocomplete-country item="{{request.country}}" required error-message="Field is required"></autocomplete-country>
</form>
</iron-form>
Taken from the iron-form documentation:
<iron-form> is an HTML <form> element that can validate and submit any custom elements that implement Polymer.IronFormElementBehavior.
So I guess your element should implement that and you´re good to go.
Solved this problem by adding new parameter required and adding it as attribute :
<paper-autocomplete ... required$="[[required]]" ... ></paper-autocomplete>
Related
I am trying to create a datasource for a Kendo Grid in Vue.js. I need to put auth headers so declarative syntax in the template does not fix my problem.
The link below makes it possible for an array, but I need an example with an AJAX call or a promise (an Axios one would be perfect).
Kendo UI Grid Data variable Vue.js
A much cleaner answer came from Telerik support today. It make the world a better place :)
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-vue-ui/wrappers/dropdownlist/index">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.material.mobile.min.css" />
<script src="https://kendo.cdn.telerik.com/2017.3.1018/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.3.1018/js/kendo.all.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser-polyfill.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/#progress/kendo-all-vue-wrapper/dist/cdn/kendo-all-vue-wrapper.min.js"></script>
</head>
<body>
<div id="example">
<div id="app" class="demo-section k-content">
<h4>Find a product</h4>
<kendo-datasource ref="datasource"
:type="'odata'"
:server-filtering="true"
:transport-read="{ url: 'https://demos.telerik.com/kendo-ui/service/Northwind.svc/Products', beforeSend: onBeforeSend }">
</kendo-datasource>
<kendo-dropdownlist ref="dropdownlist"
:data-text-field="'ProductName'"
:filter="'contains'"
:auto-bind="true"
:data-source-ref="'datasource'">
</kendo-dropdownlist>
</div>
</div>
<style>
.demo-section .k-dropdown {
width: 100%;
}
</style>
<script>
new Vue({
el: '#app',
methods: {
onBeforeSend: function(xhr) {
var token = "asd81237hdbsjkfh234uygr38fg73";
xhr.setRequestHeader('Authorization', 'Bearer ' + token)
}
}
})
</script>
</body>
</html>
Ok, so the documentation is a bit flaky, but I managed to get a custom function going in Vue, just like in the plain Kendo UI datasource. Look at this demo for reference: http://dojo.telerik.com/uXELIh
This is a mix of declarative and custom methods, so it might look a bit odd. (I've never worked with the VUE wrapper before)
Instead of the transport-read-url="uri/to/somewhere" property just define a transport-read="readData" property.
<kendo-datasource ref="datasource1"
:transport-read="readData"
:schema-model-id="'ProductID'"
:schema-model-fields="schemaModelFields"
:batch='true'
:page-size='20'>
</kendo-datasource>
Then create the readData method:
new Vue({
el: '#app',
data: {
schemaModelFields: {
/*...*/
}
},
methods:
readData: function(e) {
//this simply returns one Product with a name Chai as a dummy
//set your Auth headers here, do the request and then pass
//the data in the e.success method as a parameter
e.success({ProductName: "Chai"})
}
}
/*...*/
});
That's all there is.
However If you have an Auth header, that you need to prepend to all your ajax requests, I'd suggest you use $.ajaxSetup() (How can I add a custom HTTP header to ajax request with js or jQuery?). This will save you the hassle of implementing this for read, update, create and delete, each and every time.
$.ajaxSetup({
headers: { 'x-my-custom-header': 'some value' }
});
A bit painful but I was able to do it with Marco's help
Here is the code
<template>
<div>
<kendo-datasource ref="datasource1"
:transport-read="readData"
:batch='true'
:page-size='20'>
</kendo-datasource>
<kendo-grid :height="550"
:data-source-ref="'datasource1'"
:pageable='true'>
</kendo-grid>
</div>
</template>
<script>
export default {
name: 'grid',
computed: {
token () {
return this.$store.state.access_token
}
},
methods: {
readData: function (e) {
console.log(this.token)
var tkn= this.token
$.ajax({
url: 'http://127.0.0.1/AssetExtranet.WebAPI2/api/Vw_Hmn_Branch',
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + tkn)
},
dataType: 'json',
success: function (data) {
e.success(data)
},
type: 'GET'
})
}
}
}
</script>
Thank Marco and Vue is perfect and super fast. It is a joy to work with Vue after that Angular 2,3,4,5... mess.
Below code has been thankfully provided by machun for toggling between RTL and LTR directions in Kendo UI widgets.
The code consists of:
HTML:
kendo autocomplete form plus a button to activate support for RTL and LTR language.
Script:
k-rtl class container
datasource (json file)
kendo autocomplete widget initializing + template to show image beside data and to open data links in the same tab
k-rtl class
The problem is that links don't open correctly. It shows a 404 Not Found error plus a /undefined at the end of the URL.
Live demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>
</head>
<body>
<div id="container">
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<input id="autocomplete" type="text" />
</div>
</body>
</html>
<script>
/*------k-rtl class container----------*/
function createAutoComplete(){
if($("#autocomplete").data("kendoAutoComplete") != null){
$("#autocomplete").parent().remove();
$("#container").append("<input id='autocomplete' type='text' />")
}
/*------datasource (json file)---------*/
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "json.txt",
dataType: "json",
data: {
q: "javascript"
}
}
},
schema: {
data: "results"
}
});
/*------kendo autocomplete widget initializing + template to show image beside data and to open data links in the same tab----------*/
$("#autocomplete").kendoAutoComplete({
dataSource: dataSource,
dataTextField: "name",
template: '<span><img src="/kendo-autocomplete-test/img/#: id #.jpg" /></span>' + '<span data-href="#:link#">#:name#</span>',
select: function(e) {
var href = e.item.find("span").data("href");
location.assign(href);
}
});
}
/*------k-rtl class----------*/
createAutoComplete();
$('#toggleRTL').on('click', function(event) {
var form = $('#container');
console.log(form);
if (form.hasClass('k-rtl')) {
console.log("test1");
form.removeClass('k-rtl')
} else {
console.log("test2");
form.addClass('k-rtl');
}
createAutoComplete();
})
</script>
I advice to debug your function first then simply check the variable and make sure it contain the right thing. You overlooked a simple thing that your jquery dom selector isn't quite right resulting var href contain "undefined".
Change
var href = e.item.find("span").data("href");
To
var href = e.item.find("span[data-href]").attr("data-href");
Take a look here
I've got a Polymer (1.0) app that loads a list of books from AJAX:
book-service/book-service.html:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="book-service">
<style>
</style>
<template>
<iron-ajax
auto
url="https://example.com/books.json"
handle-as="json"
on-response="booksLoaded"></iron-ajax>
</template>
<script>
Polymer({
is: 'book-service',
properties: {
books: { type: Array }
},
created: function(){
this.books = [];
},
booksLoaded: function(request){
this.books = request.detail.response
}
});
</script>
</dom-module>
components/book-list.html:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../book-service/book-service.html">
<dom-module id="book-list">
<style>
</style>
<template>
<book-service id="service" books="{{books}}"></book-service>
<div>
<div>Books:</div>
<ul>
<template is="dom-repeat" items="{{books}}">
<li>{{item.title}}</li>
</template>
</ul>
</div>
</template>
<script>
Polymer({is: 'book-list'});
</script>
</dom-module>
While I can confirm that JSON is being received by the AJAX request, nothing is changed in the DOM. Then I noticed that the note in the Polymer 1 data binding guide that mutation requires use of Polymer methods, so I tried what was shown, and the response handler became this:
booksLoaded: function(request){
this.push('books', request.detail.response);
}
But now I get an error! Uncaught TypeError: Cannot read property 'concat' of undefined
How do I actually bind the AJAX response to the template?
Use the notify attribute to propagate the property changes up for binding.
properties: {
books: { type: Array, notify: true }
},
Additionally, you could whittle off those booksLoaded and created functions with this:
<dom-module id="book-service">
<template>
<iron-ajax
auto
url="https://example.com/books.json"
handle-as="json"
last-response="{{books}}"></iron-ajax>
</template>
<script>
Polymer({
is: 'book-service',
properties: {
books: {
type: Array,
notify: true,
value: function(){return []}
}
}
});
</script>
</dom-module>
I have a edit template using a list view and want a drop down list that is populated from a remote source. But the drop down list just shows the loading icon.
Here is the DropDownList DataSource.
var dsTitles = new kendo.data.DataSource({
transport: {
read: "../data/options/",
dataType: "json"
},
serverFiltering: true,
filter: [{
field: "category_opt",
operator: "eq",
value: "title"
}]
});
and here is what I'm putting in the edit template
<input name="title_clt"
data-bind="value:title_clt"
data-value-field="value_opt"
data-text-field="label_opt"
data-source="dsTitles"
data-role="dropdownlist"
required
validationMessage="Required" />
any help would be great.
Your code is basically fine but there a couple of question that you might have missed.
Since you are defining the DataSource saying data-source="dsTitles" as part of the HTML the order on how you define things is pretty important.
The first thing that gets defined is the HTML. Which means that dsTitle should be global.
Then, after the input is processed is when you should call kendo.init.
So, it should be something like this:
<html>
<head>
<meta charset="UTF-8"/>
<title>OnaBai - KendoUI DrowDownList</title>
<!-- Kendo UI Web styles-->
<link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="styles/kendo.default.min.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="js/jquery.min.js" type="text/javascript"></script>
<script src="js/kendo.web.min.js" type="text/javascript"></script>
<!-- Web Page styling -->
<style type="text/css">
</style>
<script type="text/javascript">
var dsTitles = new kendo.data.DataSource({
transport: {
read: "../data/options/",
dataType: "json"
},
serverFiltering: true,
filter: [{
field: "category_opt",
operator: "eq",
value: "title"
}]
});
$(document).ready(function () {
kendo.init("input");
});
</script>
</head>
<body>
<input name="title_clt"
data-bind="value:title_clt"
data-value-field="value_opt"
data-text-field="label_opt"
data-source="dsTitles"
data-role="dropdownlist"
required
validationMessage="Required" />
</body>
</html>
I think the answer might be as simple as using a Kendo DropDownListFor, which will be populated with the given data.
I have a kendo tree initialized with the following datasource:
var dataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: '/Quota/Home/GetTemplateHierarchy',
dataType: 'json',
data: { hierarchyID: hierarchyID, quotaSetID: quotaSetID, batchSize: 10 }
}
},
schema: {
model: {
id: 'id',
hasChildren: 'hasChildren',
children: 'items',
fields: {
text: 'text'
}
}
}
});
Does anyone know how to add and create a new node for this datasource? I've tried the generic treeview.append({ text: "Boo"}) but it doesn't do anything. I've successfully removed nodes, but can't seem to add any. The documentation is not clear as to how to add anything when using custom schemas.
Not sure what do you want to be the text of the node that you want to display. So I will guess that you want to display the only element in the schema nodelevel
The data in that case should be: { nodelevel : 99 }
Following a complete example where I have an initial node and then I append sub-nodes to the selected node.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Tree View</title>
<!-- Kendo UI Web styles-->
<link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="styles/kendo.default.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="js/jquery.min.js" type="text/javascript"></script>
<script src="js/kendo.web.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
var count = 0;
var data = [
{ nodelevel: count++ }
];
var dataSource = new kendo.data.HierarchicalDataSource({
data :data,
schema:{
model:{
id :'id',
hasChildren:'hasChildren',
children :'items',
fields :{
nodelevel:{
type :'number',
editable:true,
nullable:false
}
}
}
}
});
var tree = $("#tree").kendoTreeView({
dataSource :dataSource,
dataTextField:"nodelevel"
}).data("kendoTreeView");
$("#add").click(function () {
var selected = tree.select();
if (selected.length > 0) {
tree.append({ nodelevel: count++ }, selected);
}
});
});
</script>
</head>
<body>
Add to selected
<div id="tree"></div>
</body>
</html>
Paul, I'd like to propose another solution...
<!-- Kendo UI Web styles-->
<link href="../styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="../styles/kendo.default.min.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="../js/jquery.min.js" type="text/javascript"></script>
<script src="../js/kendo.web.min.js" type="text/javascript"></script>
<!-- Local Styles -->
<style type="text/css">
</style>
<!-- Initialize Form Elements -->
<script type="text/javascript">
$(document).ready(function () {
function loadMore() {
var uid = $(this).data("uid");
var node = tree.findByUid(uid);
tree.insertBefore(content, node);
tree.remove(node);
addLoadMore(".k-i-pencil");
}
function addLoadMore(clss) {
$(clss, tree.element).closest(".k-item").on("click", loadMore);
}
var content = [
{
text :"node1",
items:[
{ text:"node1.1" },
{ text:"node1.2" },
{ text:"node1.3", spriteCssClass:"k-icon k-i-pencil" },
{ text:"node1.4" }
]
}
];
var tree = $("#tree").kendoTreeView({
dataSource:content
}).data("kendoTreeView");
addLoadMore(".k-i-pencil");
});
</script>
</head>
<body>
<div id="tree"></div>
</body>
</html>
Here I create a tree with a content loaded from JSON (it should be replaced by your ajaxAntiForgery). There is one node in the tree that has an icon (k-i-pencil). Then I call a function addLoadMore that intercepts clicks on the node with k-i-pencil and add new content to this node -using insertBefore for inserting the new content before the content with k-i-pencil and then removes the old node).
I think that this example is pretty similar to what you are doing with your button.
So, take a look into loadMore function to see how I detect the node corresponding to where I clicked (I extract the uid and the find the node with this uid by using tree.findByUid).
Finally I remove the original node (invoking tree.remove) and set again the interceptor for the new nodes with k-i-pencil.
Hopefully this is pretty close to what you have.
The treeview.append should work and append new node to the root level if you do not specify a note to append it to.
You could also use the dataSource.insert({text:"foo"}) or dataSource.add.