Double click to edit element in Meteor app - javascript

I am making a school project in Meteor.js for a hospital - the prototype of the app is up on http://lrh.meteor.com . In the view doctors section in the table, I want to double click on the record and be able to edit the Name and the email id, but along with this I also want to update in record in MongoDB collection. Any ideas about how I can implement this feature?

I think this can help you.
Lets create this helper.
Template.example.helpers({
'editValue' : function(){
return Session.get("TargetValue" + this._id);
}
})
And this 2 events.
Template.example.events({
'dbclick #spanIdOnDom' : function(e,t){
return Session.set("TargetValue" + t.data._id,true)//hide the span and we set the input
},
'click #buttonToSaveNewValue': function(e, t) {
//here you can take the emailId and the name based on this._id like this Collection.find({_id:this._id}).fetch(); and do the updates you want to do
var newValueFromInput = document.getElementById('newValueFromInput').value;
var idCurrentDocument = this._id;
var Bebida = Collection.findOne(t.data._id);
Collection.update({_id: idCurrentDocument}, {$set:{fieldToUpdate: newValueFromInput}});
return Session.set("TargetValue" + t.data._id,false); //we hide the input and we put the span again
}
})
HTML
<template name="example">
{{#each collectionFind}}
{{#if editValue}}
<input type="text" id="newValueFromInput" value="{{currentValue}} " />
<button class="btn btn-sm btn-primary" id="buttonToSaveNewValue" type="submit">Save new Value</button>
{{else}}
<td>
<p>
<span class="content col-md-10" id="spanIdOnDom" ><h4>Descripcion Bebida:</h4><br>{{currentValue}} </span>
</p>
</td>
{{/if}}
{{/each}}
</template>
Of course you need to set your Allow/deny Permission and publish/subscribe methods to make it work more efficient.
How it works?
in resume you have an <span> tag with the current value, when you dobleClick on the <span> tag , we set the Session to true, the <span> tag go away and a new <input> appears with a new button then we take the value from the <input> and she update ($set) into the collection, and its done.
NOTE: this is a mini-repo from Simple Crud app in Meteor from Raj Anand, but the code on the blogs is on coffee and i don't use coffee Script.

Related

How to pass a variable to a helper and display its in the template?

I'd like to collect a variable(user _id)collected from a template, and pass it to another template using session. Then I want to display this variable.
Actually it seems to work in the collection of the variable and the pass to the other template, but I'm not able to display the user's info in the second template...
This is my code:
HTML
<template name="main"><!--Template 1-->
<table>
<tr>
<th>Patient</th>
</tr>
{{#each allUsers}}
<tr>
<th><label><input type="radio" class="selected" name="patient" value="{{this._id}}"><i class="fa fa-user"></i> {{this.profile.lastName}} {{this.profile.firstName}}</label></th>
</tr>
{{/each}}
</table>
{{>test}}
</template>
<template name="test"> <!--Template 2-->
<p>Name is <button class="test" name="patient" value="{{this._id}}">Test</button></p>
<div name="show">Name: {{this.profile.firstName}}</div>
</template>
JS
Template.main.events({
'click .selected': function (){
var selPat = $('input[name="patient"]:checked').val();
Session.set("selPat",selPat);
console.log("collect", selPat);
}
});
Template.test.events({
'click .test': function(){
var PAT= Meteor.users.findOne({ _id: Session.get("selPat")});
console.log("pass", PAT);
return PAT;
}
});
Template.patients.helpers({
allUsers: function() {
return Meteor.users.find({});
}
});
I want to display in the template 2 the first name of the user selected in the template 1 with {{this.profile.firstName}}
I believe this is what you are doing:
You are choosing patient's id from a list of patients via the radio buttons in the main template. [this implementation is correct]
You are setting the patient id in a session in the main template's events. [this implementation is correct]
When you click the "test" button in the test template, it should reveal the user's first name in the div below the button. [...not quite]
You are unable to display anything in <div name="show">Name: {{this.profile.firstName}}</div> because you don't have a relevant helper supplying the template with that information.
Although clicking a button to reveal the patient's firstName in the test template sounds a bit redundant, I'm sure you have some reason to do it in that manner.
I propose that you wrap the div inside an if block. The if condition renders true, when the button is clicked, and hence the div element is shown.
<template name="test"> <!--Template 2-->
<p>Name is <button class="test" name="patient" value="{{this._id}}">Test</button></p>
{{#if isButtonClicked}}
<div name="show">Name: {{data.profile.firstName}}</div>
{{/if}}
</template>
Your helpers and events will be like so:
Template.test.events({
'click .test': function(){
// set this session to true when the button has been clicked.
Session.set("testClicked", true);
}
});
Template.test.helpers({
isButtonClicked: function(){
// return the if block's validation.
return Session.get("testClicked");
},
data: function(){
// return the actual user data retrieved from the collection.
var PAT= Meteor.users.findOne({ _id: Session.get("selPat")});
console.log("pass", PAT);
return PAT;
});
Note:
You might want to make sure that the div does not stay open when you select a different patient from the list of radio buttons. Not doing so will make the div be visible when you first click the button, and remain open until you refresh the page, even when you select a different patient.
You could set testClicked to false or undefined in Template.main.events --> 'click .selected'

Adding and removing Meteor templates

For a Meteor application I'd like the users to be able to add divs to a column by clicking on a button, with each of these having a button to remove the div. Here's an extract of the code:
<template name="MainTemplate">
....
<a class="btn btn-sm" class="add-dynamic"></a>
<div id="add-stuff-here"></div>
....
</template>
<template name="DynamicTemplate">
<div id="dynamic-{{uniqid}}">
<a class="btn btn-sm delete-dynamic" name="{{uniqid}}"></a>
</div>
</template>
...and in the javascript file:
Template.MainTemplate.events({
'click .add-dynamic'(event) {
const random = String.fromCharCode(65 + Math.floor(Math.random() * 26));
const uniqid = random + Date.now();
Blaze.renderWithData(Template.DynamicTemplate, {uniqid: uniqid}, $("#add-stuff-here")[0])
},
})
Template.DynamicTemplate.events({
'click .delete-dynamic'(event){
const target = event.target || event.srcElement;
const id = target.id;
console.log("Button ID: " + id); // This is null
new = $('#dynamic-' + id);
new.parentNode.removeChild(new); // Therefore, this fails
}
});
Adding the templates works as expected but deleting them fails as the id of the clicked button appears to be nil.
In any case I'm probably going about this in completely the wrong way (I haven't used Meteor for a long time and didn't know it very well anyway), and so would appreciate any suggestions as to how this might be accomplished.
ETA: The possible answer suggested in the comments includes:
UI.remove(self.view);
...which "expects a template rendered with Blaze.render". I'm not able to determine how to pass the identity of the template to be removed to the function which is run on the button click - does anyone have any suggestions?
In the end I worked around it by doing this:
<template name="DynamicTemplate">
<input type="text" class="dynamic-input" placeholder="Some text" />
</template>
Template.DynamicTemplate.events({
'click .delete-dynamic'(event){
inputs = $(".dynamic-input").length;
if ( inputs > 1 ) {
const element = $(".dynamic-input")[dynamic - 1];
element.parentNode.removeChild(element);
}
}
});
That seems to do more-or-less what I was after and avoids the problem of the null ID which I mentioned in the original post.

Handlebar.js template with dynamic form inputs using Underscore.js - Zendesk App

I am trying to figure out how to submit and capture all form inputs in a dynamically created form on a Handlebar.js template using Underscore.js. This is occurring in a Zendesk custom app.
There is a .hdbs template and app.js file in the scenario. The form loads and shows correctly. The underscore.js function I am using does see the form input but only returns the very first input value/key. It does not return the dynamically generated list of checkboxes.
.hdbs:
<div class="row-fluid">
<p>
</p>
<form id="updateChecklist">
{{listname}}: {{complete}} / {{total}}
<input type="hidden" name="listid" value="{{listid}}">
<br/>
<ul>
{{#each tasks}}​
<li class={{fontcolor}}>
<input type="checkbox" name="{{this.id}}" id="{{this.id}}" {{ this.state }}> {{this.name}}
</li>​
{{/each}}
</ul>
<button class="btn btn-inverse btn-large" id="update" type="button">Update Tasks</button>
</form>
</div>
app.js:
events: {
'click #update' : 'updateSingleChecklist'
},
...
updateSingleChecklist: function(event) {
var serializedArray = this.$("#updateChecklist").serializeArray();
var itemIdsArray = _.map(serializedArray, function(item, key){
return {item, key};
});
console.log(JSON.stringify(itemIdsArray));
Current Incorrect Result:
[{"item":{"name":"listid","value":"56eafe771e9824def46a7d7d"},"key":0}]
What I am looking for is an array of the form inputs, including unchecked checkboxes.
I need:
[{"item":{"name":"listid","value":"56eafe771e9824def46a7d7d"},
{"name":"checkbox1","value":"56eafe771e9824def46a7d8c", "checked":"0"},
{"name":"checkbox2","value":"24eafe771e9824def46a7c6d", "checked":"1"},
{"name":"checkbox3","value":"71eafe771e9824def46a3r5g", "checked":"0"},
...
"key":0}]
It turned out to be lot simpler than I initially realized. The solution to this issue for now is updated at https://jsfiddle.net/sde13q3m/3/ .
Essentially, the map array function with a simple evaluation in the return statement allowed me to collect all form fields and checkboxes for the controller.
var serialized = this.$('#myform input').map(function() {
return { name: this.name, id: this.id, value: this.checked ? "checked" : "false" };
});

Getting Value from Dynamic Url and Post it into HTML/PHP by Using AngularJS

I would like to ask whether I can get the data from dynamic URL... Here is the case:
I have given an (a) html tag into my angularJS php file to give direction to certain page with the value inside it e.g. localhost:8080/someurl/blablabla/{{item.master}} so the output is based on what I have clicked... so it will be localhost:8080/someurl/blablabla/221
After that, I have a laravel 5.2 and given a route based on this dynamic url, e.g. Route::get('order/{id}','someController#index')
After this route, I have prepared the php files and it is ready to display the data
The problem is, I don't know which angularJS code that I should use to display the data based on the {{item.master}} in this new page, when I use $http.get, it doesn't get anything, is there any clue about this?
UPDATED
Here is the codes:
HTML (order.html)
<div class="itemcheck" ng-repeat="item in dataItem.stores | regex:'name':alfabet | orderBy: 'name' | filter: searchItem" ng-model="item">
<div class="left" ng-if="item.preparation == ''" ng-click="klikItem(item)"><i class="fa fa-circle silver"></i>{{item.name}}</div>
<div class="left" ng-if="item.preparation == '1'" ng-click="klikItem(item)"><i class="fa fa-circle green"></i>{{item.name}}</div>
<div class="left" ng-if="item.preparation == '2'" ng-click="klikItem(item)"><i class="fa fa-circle yellow"></i>{{item.name}}</div>
<div class="left" ng-if="item.preparation == '3'" ng-click="klikItem(item)"><i class="fa fa-circle pink"></i>{{item.name}}</div> <div class="right" ng-click="tambahItem(item)"><a>+ Tambahkan</a></div></div>
Let's not focus on "tambahkan" but the item.name when I put klikItem function
So, when I click, the klikItem() function is triggered (what I want) or let's say I put the tag a inside the {{item.name}} function and when I click that it goes to order/{{item.id}} (somehow like that)...
Nah, the problem is, how can I get the data from order/{{item.id}}? If I use $http.get, it must have the data, and when I put id for example
$scope.tampilkanDeskripsiItem = function(id){
var url = 'order/' + id;
$http.get(url).success(function(data){
$scope.deskripsiItem = data;
});
};
$scope.tampilkanDeskripsiItem();
this code will return error as "id" is not defined...
You can assign id inside klikItem (if item object has id property.)
function klikItem(item){
$scope.tampilkanDeskripsiItem(item.id);
}

Update documents based on multiple dropdown values

I am building an administration panel within a meteor app to be able to manage the users of the app. Currently I am displaying all the users with a dropdown for each user to change their role .
I need to update the changed roles only after I hit some confirmation button at the end.
I have a template that gets rendered with the username and a dropdown with the current role of the user, my template is similar to this:
<div class="ui selection dropdown">
<input type="hidden" name="role">
<i class="dropdown icon"></i>
<div class="default text">{{role}}</div>
<div class="menu">
<div class="item" data-value="admin">Admin</div>
.
.
.
<div class="item" data-value="user">User</div>
</div>
</div>
This renders as many as users I have in my database. I need to update all users who have their role changed after clicking a button.
My current approach is to plug the user id to the dropdown:
<div class="ui selection dropdown" id={{_id}}>
Then I have an event handler for the dropdown change and catch the value:
Template.templateName.events({
"change .ui.selection.dropdown": function(event, template) {
var id = template.find(".ui.selection.dropdown").id;
var role = template.find("input[name=role]").value;
...
},
});
Now I am wondering if I should push those id,role pairs in some session key and update the users after clicking save button or there is a better and more effective alternatives for this ?
Instead of saving them in session variable and clearing session variable on template's destroyed callback, you can add an attribute to the changed element indicating that the element has changed. When save button is clicked, you can use attribute selector to get all the elements that were changed by this user. See the code sample below for further reference.
Template.templateName.events({
"change .ui.selection.dropdown": function(event, template) {
var target = $(event.target);
target.attr("data-changed", "data-changed");
},
"click #saveButtonId": function(event, template) {
var changedElements = template.$(".ui.selection.dropdown[data-changed]");
var changedItems = [];
for (var i = 0; i < changedElements.length; i++) {
var changedElement = changedElements[i];
changedItems.push({ id: changedElement.id, value: changedElement.value });
// or
//changedItems.push([changedElement.id, changedElement.value]);
}
// here you can call a meteor method like
// Meteor.call('updateUserRoles', changedItems); //this updateUserRoles will now get only changed items that you can update in your DB.
}
});

Categories

Resources