How to select an element inside a dom-module in polymer 1.0? - dom

I have the following dom-module that I am trying to create interactions for.
<dom-module is="bw-image-upload">
<template>
<vaadin-upload id="uploader"
target="{{ API_URL}}/images/upload"
method="POST"
max-files="1"
max-file-size="200000"
accept="image/*"
upload-success="uploadResponseHandler"
file-reject="errorHandler"
>
</vaadin-upload>
</template>
<script>
Polymer({
is: 'bw-image-upload',
properties: {
image: String,
notify: true
}
});
var uploader = document.querySelector('#uploader');
uploader.addEventListener('upload-before', function(event) {
console.log(event);
});
</script>
</dom-module>
I want to select the vaadin-upload element by it's ID but it returns a null and I am confused on why it is returning null.
How do I select an element like this in Polymer?

If the element has an id and is statically added to the template, you can use
var uploader = this.$.uploader;
to get a reference to an element with the id uploader.
If the element is inside <template is="dom-if">, <template is="dom-repeate"> or otherwise dynamically created this is not supported.
In such cases you can use
var uploader = this.$$('#uploader');
this.$$(...) provides full CSS selector support and returns the first matching element, while this.$... only supports IDs.

Related

VueJs - How to access DOM property of an element from $refs

I have an element
<tbody ref="tbody">
<tr class="row" :ref="userIndex" v-for="(userData, uid, userIndex) in users" :key="uid">
in my template. I need to access/edit the DOM property like scrollTop, verticalOffset of <tr> element. How can I achieve this?
I have tried to access using this.$refs[userIndex][0].$el but its not working. I can see all the properties in the console but I am unable to access them. However this.$refs.tbody.scrollTop works.
Below is the snap showing console.log(this.$refs)
console.log(this.$refs[userIndex])
console.log(this.$refs[userIndex][0])
As you can see when I use this.$refs[userIndex][0] I don't see the DOM properties
A $ref object will only have a $el property if it is a Vue component. If you add a ref attribute to a regular element, the $ref will a reference to that DOM Element.
Simply reference this.$refs[userIndex][0] instead of this.$refs[userIndex][0].$el.
To see the properties of that element in the console, you'll need to use console.dir instead of console.log. See this post.
But, you can access properties of the element like you would any other object. So, you could log the scrollTop, for instance, via console.log(this.$refs[userIndex][0].scrollTop).
I don't think verticalOffset exists. offsetTop does. To console log an Dom element and its property, use console.dir
Open the browser console and run this working snippet:
var app = new Vue({
el: '#app',
data: {
users: {
first: {
name: "Louise"
},
second: {
name: "Michelle"
}
}
},
mounted() {
console.dir(this.$refs[1][0])
console.log('property: ', this.$refs[1][0].offsetTop)
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<table><tbody ref="tbody">
<tr :ref="userIndex" v-for="(userData, uid, userIndex) in users" :key="uid">
<td>{{userData}}: {{userIndex}}</td>
</tr>
</tbody>
</table>
</div>

Couldn't manipulate Images.find() in CollectionFS for MeteorJS app

My app is sort of like TelescopeJS, but a lot simpler. I'm trying to echo the particular image that has been added in the post-adding form which takes an input of the name of the post, picture, categories and description. It has 2 collections, one for Articles and the other for Images (NOT a mongo collection, it's an FS collection.) The articles collection stores the name,description and category name and the other one stores image. **My Problem is: ** in the FS collection doc, the loop
{{#each images}}
<img src="{{this.url}}" alt="" class="thumbnail" />
{{/each}}
Where images: returns Images.find({}) and my articles code is :
{{#each articles}}
<li style="margin-right: 1%;">{{>article}}</li>
{{/each}}
Where articles: returns Articles.find({})
MY articles template HAS the images loop and this causes ALL THE IMAGES in the collection to be shown in one post. I just want specific images to be shown for the specific post.
These are the events:
'change .img': function(event, template) {
FS.Utility.eachFile(event, function(file) {
Images.insert(file, function (err, fileObj) {
//Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
});
});
},
'click .save':function(evt,tmpl){
var description = tmpl.find('.description').value;
var name = tmpl.find('.name').value;
var date=new Date();
var cat = tmpl.find('.selectCat').value;
Articles.insert({
description:description,
name:name,
time:date.toLocaleDateString()+' at '+date.toLocaleTimeString(),
author:Meteor.userId(),
userEmail:Meteor.user().username,
category:cat,
});
}
<template name="article">
{{#each images}}
<img src="{{this.url}}" alt="" class="thumbnail" />
{{/each}}
Here goes the {{name_of_post}}
Here {{the_category}}
Here {{the_description}}
</template>
So what happens is, all the images that I've uploaded so far shows in one post and all the posts' picture looks the same. Help please!
You should know that fsFile support Metadata so maybe you don't need the Articles Collection
So we can make a new eventHandler.
'click .save':function(evt,tmpl){
var description = tmpl.find('.description').value,
file = $('#uploadImagePost').get(0).files[0], //here we store the current file on the <input type="file">
name = tmpl.find('.name').value,
date=new Date(),
cat = tmpl.find('.selectCat').value,
fsFile = new FS.File(file); // we create an FS.File instance based on our file
fsFile.metadata = { //this is how we add Metadata aka Text to our files
description:description,
name:name,
time:date.toLocaleDateString()+' at '+date.toLocaleTimeString(),
author:Meteor.userId(),
userEmail:Meteor.user().username,
category:cat,
}
Images.insert(fsFile,function(err,result){
if(!err){
console.log(result) // here you should see the new fsFile instance
}
});
}
This is how our new event will look, now our .save button insert everything on the same collection.
This is how we can access to the FS.File instances fields using the keyword 'metadata.fieldName'.
For example.
Teamplate.name.helpers({
showCategory:function(){
// var category = Session.get('currentCategory') you can pass whatever data
// you want here from a select on the html or whatever.
//lets say our var its equal to 'Music'
return Images.find({'metadata.category':category});
}
})
Now we use that helper on the html like any normal collection
<template name="example">
{{#each showCategory}}
Hi my category is {{metadata.category}} <!-- we access the metadata fields like any normal field on other collection just remember to use the 'metadata'keyword -->
This is my image <img src="{{this.url}}" >
{{/each}}
</template>

Polymer: passing attributes from container component to an item component

I have 2 components:
x-container and x-item.
they have a hierarchy similar to < table > and < tr > or to < tr > and < td >...
Hence x-item components are only effective when they're inside an x-container component:
<x-container>
<x-item></x-item>
</x-container>
I want to pass an attribute value from x-container to x-item:
<x-container att="value">
<x-item></x-item>
</x-container>
In this case I need value to be visible to x-item - is it possible?
Thanks!
It works out of the box if you know the structure of x-container beforehand (JSBin):
<polymer-element name="x-container" attributes="value">
<template>
<x-item value="{{value}}"></x-item>
</template>
<script>
Polymer('x-container', {
value : null,
ready: function() {
}
});
</script>
</polymer-element>
<polymer-element name="x-item" attributes="value">
<template>
<div>x-item value:{{value}}</div>
</template>
<script>
Polymer('x-item', {
});
</script>
</polymer-element>
<x-container value="test"></x-container>
If you want to dynamically create the relationship of x-container and x-item refer to these SO threads:
Data-binding between nested polymer elements
Using template defined in light dom inside a Polymer element
What is the best way to implement declarative collection rendering with Polymer?

How do I get element related to active input in jQuery UI Autocomplete?

I'm trying to pass a custom form attribute (category) through jQuery UI Autocomplete to use in a product search. The form looks like <form id="BulkOrderForm" category="samplecategory"><input></input>...</form> and contains inputs that use the autocomplete script. There can be several forms on each page, so I need to be able to get the category value from the form that contains the active input field.
Here's my source:
function autocomplete() {
$("input.wcbulkorderproduct").autocomplete({
element: function(){
var element = $('form#BulkOrderForm').attr('category');
return element;
},
source: function(request, response, element){
$.ajax({
url: WCBulkOrder.url+'?callback=?&action='+acs_action+'&_wpnonce='+WCBulkOrder.search_products_nonce,
dataType: "json",
data: {
term: request.term,
category: element
},
success: function(data) {
response(data);
}
});
}
});
}
Any thoughts on how this can be acheived?
If I'm understanding correctly, you're trying to use the active input's parent form in the ajax request. Here's a way to achieve that:
Html:
<form data-category="form1">
<input type="text" />
<input type="text" />
</form>
<form data-category="formB">
<input type="text" />
<input type="text" />
</form>
JS:
$('form').each(function () {
var category = $(this).data('category');
$(this).find('input').autocomplete({
source: function (request, response) {
response([category]);
}
});
});
Instead of using autocomplete on a catch-all selector that gets inputs from all forms, first select the forms themselves. For each one, extract the category, then select all child inputs and call autocomplete on that result. Then you can use the category variable in the ajax call - in the example I'm simply passing it to the callback to display.
http://jsfiddle.net/Fw2QA/
I'll give you another solution, you can lookup the parent form of the active input, and extract the attribute from it. Because I don't know if this category in your form is dynamic or no, or either if you can control all of the process involved in your code, I'll give you a more generic solution, although if that attribute is dynamic "Turch" solution is way better than mine, by letting the data functionality of jquery handle the attribute changes, if it's static, than you can just do it like this:
function autocomplete() {
var element = $("input.wcbulkorderproduct").autocomplete({
source: function(request, response){
$.ajax({
url: WCBulkOrder.url+'?callback=?&action='+acs_action+'&_wpnonce='+WCBulkOrder.search_products_nonce,
dataType: "json",
data: {
term: request.term,
category: element
},
success: function(data) {
response(data);
}
});
}
}).parents('form').first().attr('category');
//chained call, sets autocomplete, grabs the parent form and the attribute
//which is saved on the variable element, and is used on every call through
//javascript context inheritance.
}
UPDATE
A little example illustrating my suggestion (provided by #Turch > thanks), can be found here.

getting class attr in jquery

I have some divs that are generated dynamically with content. I add the content id to the class for the div like so:
<div class="div-1"></div>
<div class="div-3"></div>
<div class="div-6"></div>
<div class="div-8"></div>
How do I select the id for a div because I need it as a param to send via ajax. e.g. I need to get the 1 when I click on the 1st div, 3 when I click on 2nd and so on
var id = $(this).attr('class').replace('div-', '');
Or even simple
var id = this.className.replace('div-', '');
Where this points to the dom element you click on inside the click handler.
//Here instead of document it is better to specify a parent container of all divs
$(document).on('click', '[class^="div-"]', function(){
var id = this.className.replace('div-', '');
});
Try this, and remember changing "div" for your selector:
$(document).on("click", "div", function() {
var class_elem = $(this).attr("class").split("-");
var n = class_elem[1]; // This is your number
});
The correct jQuery syntax is:
$("div").click( function() {
var id = $(this).attr('class').replace('div-', '');
});