Getting the value of element clicked on in Emberjs - javascript

I have a series of labels that I would like to retrieve the text from when the user clicks on them. I thought the jquery might be doable in Emberjs:
$(this).attr('text');
This however, doesn't work with Ember. My component view is this:
<ul class="list-inline">
{{#each model as |model|}}
<li {{action "sendToInput"}} class="label label-default">{{model.name}}</li>
{{/each}}
</ul>
I would like to retrieve that model.name value via the action "sendToInput".
In my component js file I have tried:
actions: {
sendToInput() {
$(this.target).attr('text');
}
}
I have also tried:
this.innerHTML;
$(this).text();
this.get('text');
$(this).val();
I have also opened up the console and dug through this and cannot seem to find where they store the element clicked on.
The documentation doesn't mention this and there's no issue I can find on the Github for ember-cli.
Thanks.

The common way is to pass a model name as an action parameter like this:
<ul class="list-inline">
{{#each model as |model|}}
<li {{action "sendToInput" model.name}} class="label label-default">{{model.name}}</li>
{{/each}}
</ul>
and then handle it in the action:
actions: {
sendToInput(name) {
// do something with name
}
}
But if you still need to access the exact element's html, there is another workaround:
export default Ember.Component.extend({
didInsertElement () {
this.$().on('click', '.label', function (event) {
$(this).text();
})
}
});

Related

VueJS/Laravel - Sharing props between Laravel and Vue

I have defined a component called EditorNavigation.vue like so:
<template>
<div>
<ul>
<li v-bind:class="{'is-active':(active === field.id)}" v-for="field in fields">
<a :href="'/streams/' + stream_token + '/fields/' + field.id">{{field.name}}</a>
</li>
</ul>
<div>
</template>
<script>
export default {
props: ["fields", "active", "stream_token"],
created() {
this.fields = JSON.parse(this.fields);
this.active = JSON.parse(this.active);
this.stream_token = JSON.parse(this.stream_token);
}
};
</script>
As you can see in my component, I need three variables:
Fields (array of all fields)
An unique token for a specific resource
The current active field id (so I can set the is-active class).
In my Laravel view file, I use the component like this:
show.blade.php
<editor-navigation fields="{{ json_encode($stream->fields) }}" active="{{ json_encode($field->id) }}" stream_token="{{ json_encode($field->stream->token) }}"></editor-navigation>
So above code works fine, however it feels a bit "messy" - since I need to use the editor-navigation component in a lot of pages, and I am wondering what will happen as soon as I need another variable sent to it - I have to update it in all places.

Show/hide an element within one list item, not all of them

I've generated a dynamic list of comments on a post from my server in Vue, and would now like a 'reply' button to appear on each comment that when clicked opens a textarea underneath it and is linked to that comment. However, my hacky solution meant that clicking on it opened all of the comments' text boxes, not just one.
How can I target each comment individually with a show/hide function in Vue?
I know why my solution isn't working—but I don't know where to start making a function that targets the specific comment on clicking it.
Template (HTML)
<ul>
<li v-for="comment in comments" :key="comment.data.id">
<div>User details</div>
<div>Comment content</div>
<div>
<span>
<a v-on:click="hideReply = !hideReply">Reply</a>
</span>
</div>
<form v-if="hideReply">
<textarea>Reply text box</textarea>
<button>Reply button</button>
</form>
</li>
<li>Another comment in the list...</li>
<li>Another comment in the list...</li>
...
</ul>
Script (JS)
export default {
name: 'Post',
components: {},
data () {
return{
hideReply: false,
comment: undefined,
comments: undefined
}
},
async created () {
// code to bring in my comments from server
},
methods: {
betterShowHideFunction () {
// where do i start
}
}
}
Add a show property on each comment and use that for showing/hiding each individual comment
<form v-if="comment.show">
Change the var accordingly
<a v-on:click="comment.show = !comment.show">Reply</a>

Remove mongodb documents from a collection by an array of _ids

Using Meteor, I have a collection for Contacts which I list with a checkbox beside each contact.
I want to be able to select multiple checkboxes and then click a button to delete the selected contacts from the Contacts collection.
With the code I have below, the selected _ids show up in an array in the console, but nothing is being deleted and no error is being produced.
contacts.html
<template name="contacts">
<h1>Contacts</h1>
<ul>
{{#each contacts}}
{{> contact}}
{{/each}}
</ul>
<br/>
Create Contact
<a class="delete-selected" href="">Delete Selected Contacts</a>
</template>
contact.html
<template name="contact">
<li style="list-style:none;">
<input id="{{_id}}" type="checkbox" value="{{_id}}" name="contact"/>
<span class="contact">{{firstName}} {{lastName}} <strong>{{company}}</strong></span> {{#if contactType}}({{contactType}}){{/if}}
</li>
</template>
Client JS
Template.contacts.events = {
'click .delete-selected': function(e) {
e.preventDefault();
var selectedContacts = [];
$('input[name=contact]:checked').each(function() {
selectedContacts.push($(this).val());
});
Meteor.call('removeSelectedContacts', {selectedContacts: selectedContacts});
}
Server JS
Meteor.methods({
removeSelectedContacts: function(selectedContacts) {
Contacts.remove({_id:{$in:[selectedContacts]}})
//Contacts.remove({selectedContacts});
console.log(selectedContacts);
}
});
Thanks
#corvid: I think you can only remove one at a time on the client (by _id)
#serks: you have an extra array level in there, in your method just do:
Contacts.remove({ _id: { $in: selectedContacts }});
There's also an error in how you're calling the Method, instead of:
Meteor.call('removeSelectedContacts', {selectedContacts: selectedContacts});
Simply pass the parameter directly:
Meteor.call('removeSelectedContacts',selectedContacts);
The method is expecting an array, not an object.
Use the $in operator.
Template.contacts.events({
'submit #delete-contacts-form': function (e, template) {
// assumes permissions are set on server appropriately.
Contacts.remove({
_id: {
$in: $(e.target).find('input:checked').map(el => el.val()) // assumes the value of each checkbox is the _id
}
});
}
});

How to bind a Kendo UI list to a ViewModel?

I have this fallowing list:
<ul data-template="view" data-bind="source: contacts"></ul>
...
<script type="text/x-kendo-template" id="view">
<li>
<div data-role="button" data-bind="click: viewContact">
<h4>#: first_name #</h4>
</div>
</li>
</script>
var someClass = kendo.observable({
title : 'Contact',
contacts : [],
getContacts: function () {
var data = new Contacts().get();
$.when(data()).then(function (data) {
someClass.contacts = data;
});
}
});
I want to assign data from getContacts to products and populate the template with results as they come in.
Any ideas?
In your question you are talking about "products" but in the code snippet i see "contacts".
In any case, you need to do the following:
someClass.set('contacts', data)
Note: assuming you have contacts as a property on the viewmodel.
Since its an observable object, if you don't use get() & set() methods, kendo wont know who all are observing that property. If you use set() method to set new value, Kendo will propagate the change and will notify the listeners of the property.

Best way to store "temp" data on an ember button

I have an Ember.Button which should remove an element from an array. The button label is simply an X (for now).
I'd like to know the best way to store data for use by the button. If this was plain jquery I might use data-username. But what's the best way to do this?
update
Use case for this question would be something like this:
{{#each App.recentUsersArray}}
<li>
{{#view App.RecentNameBtn contentBinding="this"}} {{content}} {{/view}}
{{#view App.RecentNameDeleteBtn}}X{{/view}}
</li>
{{/each}}
In the second view, I need a way to know which username the delete action should apply to.
Use the {{action}} helper, which passes the context as argument, see http://jsfiddle.net/zVd9g/. Note: in the upcoming Ember.js version the action helper only passes one argument so you would have to adapt your sources accordingly.
If you want to use your existing views, you could do a contentBinding="this" on the App.RecentNameDeleteBtn as you already did on the App.RecentNameBtn.
Handlebars:
<script type="text/x-handlebars" >
{{#each App.arrayController}}
<button {{action "showTweets" target="App.arrayController" }} >{{this}}</button>
<button {{action "removeItem" target="App.arrayController" }}>x</button>
<br/>
{{/each}}
</script>​
JavaScript:
App = Ember.Application.create({});
App.arrayController = Ember.ArrayProxy.create({
content: [1, 2, 3, 4, 5, 6],
removeItem: function(view, evt, item) {
console.log('remove user %#'.fmt(item));
this.removeObject(item);
},
showTweets: function(view, evt, item) {
console.log('show tweets of user %#'.fmt(item));
}
});​

Categories