I am trying to provide the user with a button as follows:
<select id="test" class="btn btn-default btn-lg">
<option>Admin</option>
<option>Employee</option>
</select>
and based on the option selected, another button will appear with other choices.
Here is my code:
Template.addingUser.helpers({
userType: function () {
if(t.find('#test').value == "Admin"){
}else{
}
},
});
If am not mistaken, I can use something like:
$('#action-button').html('<a class="btn btn-primary edit_button" href="' + Template.addingUser.__helpers.get('item')().sourceCode + '" onclick="">Download</a>');
In the case of an action-button, what about select option?
Or should I follow different approach to serve my purpose?
Your code could work, but it is not how we should do in Meteor. Instead you should make the selected option value a reactive data source, when it changes you could simple you button by helper:
const selectedValue = new ReactiveVar('default_value');
Template.addingUser.helpers({
userType() {
if (selectedValue.get() === 'Admin') {
// return somehitng
} else {
}
},
});
Template.addingUser.events({
'change #test': function(e) {
selectedValue.set(e.target.value);
},
});
In this example, I use ReactiveVar to make selected option value reactive.
Updated
.js
const selectedValue = new ReactiveVar('default_value');
Template.addingUser.helpers({
isAdmin() {
return selectedValue.get() === 'Admin';
},
isNormalUser() {
return selectedValue.get() === 'User';
},
});
Template.addingUser.events({
'change #test': function(e) {
selectedValue.set(e.target.value);
},
});
.html
<template name="addingUser">
<!-- ... -->
{{#if isAdmin}}
<button>Button for admin</button>
{{/if}}
{{#if isNormalUser}}
<button>Button for normal user</button>
{{/if}}
<!-- .. .-->
</template>
Related
i have a custom input component and i want to select it without clicking on it or something so i cant use "event", i want to select it on created() or mounted()
how can i do that?
<template>
<div class="form-control">
<label :for="id">
{{ label }}
</label>
<input
:id="id"
:type="mode"
:value="currentValue"
#input="$emit('update:modelValue', $event.target.value)"
#focus="pullLabel"
#blur="pushLabel"
/>
</div>
</template>
<script>
export default {
created() {
this.test();
},
methods: {
test() {
console.log(this); // -> How could this be like '<input id="title" type="text">'
},
},
};
</script>
I figured it out myself after 6~ hours of work.
The answer is $refs
I sent a "ref" from parent component like this:
<form ref="settingsForm" #submit.prevent="updateConfig">
Then in methods, i selected all the inputs in form like this: (except submit input)
methods: {
...
focusInput() {
const inputs = this.$refs.settingsForm.querySelectorAll(
'input:not([type="submit"])'
); // $refs.settingsForm -> comes from the parent element, you can name "settingsForm" whatever you want
Array.from(inputs).map((e) => {
if (e.value.length > 0) {
e.previousElementSibling.classList.add("clicked-input");
}
});
},
...
}
By the way, the most important thing is, you have to call the function on mounted() method, not on created()
I am using Alfresco selectone.ftl to customize a dropdown list. I do not want to show any blank option as default. But the Selectone.ftl automatically adds a blank option. How to set my value as the default and delete the blank option.
There is Requirement where i have to display list of user in dropdown base on some condition , for that i have customize selectone.ftl as per below code,may be helpful to you.
** This is custom-selectone.ftl**
<div class="form-field">
<script type="text/javascript">//<![CDATA[
YAHOO.util.Event.onAvailable("${fieldHtmlId}", function(){
new selectAjax("${fieldHtmlId}");
});
function selectAjax(currentValueHtmlId) {
this.currentValueHtmlId = currentValueHtmlId;
var select = Dom.get(this.currentValueHtmlId);
this.register = function () {
Alfresco.util.Ajax.jsonGet({
url: Alfresco.constants.PROXY_URI+"userwebsacript",
successCallback: {
fn: this.updateOptions,
scope: this
},
failureCallback: {
fn: function(){},
scope: this
}
});
};
this.updateOptions = function (res) {
var result = res.serverResponse.responseText;
if (result.length > 0) {
var sp=result.split(",");
for(var i=0;i<sp.length;i++){
var option = new Option(sp[i], sp[i]);
select.options[select.options.length] = option;
}
}
};
this.register();
}
//]]></script>
<label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
<select id="${fieldHtmlId}" name="${field.name}" tabindex="0"
<#if field.description??>title="${field.description}"</#if>
<#if field.control.params.size??>size="${field.control.params.size}"</#if>
<#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
<#if field.control.params.style??>style="${field.control.params.style}"</#if>
<#if field.disabled && !(field.control.params.forceEditable?? && field.control.params.forceEditable == "true")>disabled="true"</#if>>
<option value="">Select</option>
</select>
I have a form in weather that would have had the condition User add as many lines he needs. He clicks a button and an input is added below the other.
I can do this using jQuery, but I would prefer to use the resources of Meteor. Is it possible to do?
Yes it is, here is an example from one of my apps using the underscore package
In the main template:
<template name="ask">
{{#each answerArray}}
{{>answer}}
{{/each}}
<button id="addItem">Add item</button>
</template>
<template name="answer">
<div class="input-group pt10">
<input class="form-control answer" maxlength="30" placeholder="Answer (max 30 chars)" name="answer" />
<span class="input-group-btn">
<button class="btn btn-danger delButton" id="{{id}}" data-id="{{id}}" type="button">Delete</button>
</span>
</div>
</template>
In the js file:
Template.ask.created = function () {
Session.set('action', 'ask');
answerArray = [ //adding at least two items but it could also be empty
{
id: Random.id(), //using this to give an unique id to the control
value: ''
},
{
id: Random.id(),
value: ''
}
];
Session.set('answerArr', answerArray);
}
And the click event:
Template.ask.events = {
'click #addItem': function () {
var answerArray = Session.get('answerArr');
answerArray.push({
id: Random.id() //just a placeholder, you could put any here
});
Session.set('answerArr', answerArray);
}
}
And finally the helper:
Template.ask.helpers({
answerArray: function () {
var answerArray = Session.get("answerArr")
while (answerArray.length < 2) { //i chose to have it between 2 and 6, you can remove these
answerArray.push({
id: Random.id()
})
}
while (answerArray.length > 6) { // maximum
answerArray.pop();
}
Session.set('answerArr', answerArray);
return answerArray;
}
}
This will reactively increase the number of inputs. After that, if you want to process the inputs you could do the following, on a submit form event or button click:
'click #saveQ': function (e) {
e.preventDefault();
var arr = [];
_.each($('.answer'), function (item) {
if ($(item).val() != '')
arr.push({
answer: $(item).val(), //this you customize for your own purposes
number: 0
})
});
And also if you want to delete an input from the page you can use:
Template.answer.events = {
'click .delButton': function (e) {
var thisId = $(e.target).attr("id");
var answerArray = Session.get('answerArr');
var filteredArray = _.filter(answerArray, function (item) {
return item.id != thisId;
});
Session.set('answerArr', filteredArray);
}
}
The code below shows one row from a table, and the JavaScript-code to handle the template. The code works, but it sets the disabled-attribute on all the buttons in the table. I only want it for the one button-element that is pushed.
Question: What is the best way to conditionally set the correct element as disabled in Meteor.js?
In my HTML-file:
<template name="userRow">
<tr>
<td>{{ username }}</td>
<td>
<select class="newRole">
{{{optionsSelected globalRoles profile.role }}}
</select>
</td>
<td>
Disabled: {{disabledAttr}}
{{#isolate}}
<button type="button" {{disabledAttr}} class="btn btn-xs btn-primary saveUser">Save</button>
{{/isolate}}
</td>
<td><button type="button" class="btn btn-xs btn-danger deleteUser">Delete</button></td>
</tr>
And in my .js-file:
var newUserRole;
var savedDep = new Deps.Dependency;
var saved;
var disabledDep = new Deps.Dependency;
var disabledAttr = "";
Template.userRow.saved = function () {
savedDep.depend();
return saved;
};
Template.userRow.disabledAttr = function () {
disabledDep.depend();
return disabledAttr;
};
Template.userRow.events({
'change .newRole' : function (event) {
newUserRole = event.target.value;
},
'click .saveUser' : function (event) {
disabledAttr = "disabled";
disabledDep.changed();
Meteor.call('updateUser',
{
userId: this._id,
role: newUserRole
},
function (error, result) {
if (error) {
saved = "NOT saved, try again!";
} else {
saved = "Saved!";
savedDep.changed();
};
});
return false;
}
});
To answer your question:
All of your rows are using the same Dependency object, so when one row changes the object, all the other rows respond.
To fix this you can create a new Dependency object for each row.
For example:
Template.userRow.created = function () {
this.disabledDep = new Deps.Dependency;
};
And update all of your code to use the template's disabledDep instead of the 'global' one. That should solve your problem.
But let's talk about your goal here:
It looks like you want to render your rows differently while saving, until they're confirmed server side.
A cleaner way to do this is to take advantage of Meteor's isSimulation method. For example:
// Put this in a file that will be loaded on both the client and server
Meteor.methods({
add_item: function (name) {
Items.insert({name: name,
unconfirmed: this.isSimulation});
}
});
This example is using inserts, but you can use the same technique for updates.
Now each document in your collection will have an 'unconfirmed' field, which you can use to change your view:
Template.userRow.disabledAttr = function () {
return this.unconfirmed ? "disabled" : "";
};
I'm having trouble getting Meteor.publish to update in response to a changing form field. The first call to publish seems to stick, so the query operates in that subset until the page is reloaded.
I followed the approach in this post, but am having no luck whatsoever.
Any help greatly appreciated.
In lib:
SearchResults = new Meteor.Collection("Animals");
function getSearchResults(query) {
re = new RegExp(query, "i");
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
}
In client:
Session.set('query', null);
Template.searchQuery.events({
'keyup .query' : function (event, template) {
query = template.find('.query').value
Session.set("query", query);
}
});
Meteor.autosubscribe(function() {
if (Session.get("query")) {
Meteor.subscribe("search_results", Session.get("query"));
}
});
Template.searchResults.results = function () {
return getSearchResults(Session.get("query"));
}
On server:
Meteor.publish("search_results", getSearchResults);
Template:
Search for Animals
<body>
{{> searchQuery}}
{{> searchResults}}
</body>
<template name="searchQuery">
<form>
<label>Search</label>
<input type="text" class="query" />
</form>
</template>
<template name="searchResults">
{{#each results}}
<div>
{{_id}}
</div>
{{/each}}
</template>
Update [WRONG]
Apparently, the issue is that the collection I was working with was (correctly) generated outside of Meteor, but Meteor doesn't properly support Mongo's ObjectIds. Context here and related Stackoverflow question.
Conversion code shown there, courtesy antoviaque:
db.nodes.find({}).forEach(function(el){
db.nodes.remove({_id:el._id});
el._id = el._id.toString();
db.nodes.insert(el);
});
Update [RIGHT]
So as it turns out, it was an issue with RegExp / $regex. This thread explains. Instead of:
function getSearchResults(query) {
re = new RegExp(query, "i");
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
}
At the moment, one needs to do this instead:
function getSearchResults(query) {
// Assumes query is regex without delimiters e.g., 'rot'
// will match 2nd & 4th rows in Tim's sample data below
return SearchResults.find({$and: [ {is_active: true}, {id_species: {$regex: query, $options: 'i'}} ] }, {limit: 10});
}
That was fun.
PS -- The ddp-pre1 branch has some ObjectId functionality (SearchResults = new Meteor.Collection("Animals", {idGeneration: "MONGO"});)
Here's my working example:
UPDATE the original javascript given was correct. The problem, as noted in the comments, turned out to be that meteor doesn't yet support ObjectIds.
HTML:
<body>
{{> searchQuery }}
{{> searchResults}}
</body>
<template name="searchQuery">
<form>
<label>Search</label>
<input type="text" class="query" />
</form>
</template>
<template name="searchResults">
{{#each results}}
<div>
{{id_species}} | {{name}} - {{_id}}
</div>
{{/each}}
</template>
Javascript:
Animals = new Meteor.Collection("Animals");
function _get(query) {
re = new RegExp(query, "i");
console.log("rerunning query: " + query);
return Animals.find({$and: [ {is_active: true}, {id_species: {$regex: re}} ] }, {limit: 10});
};
if (Meteor.isClient) {
Session.set("query", "");
Meteor.autosubscribe(function() {
Meteor.subscribe("animals", Session.get("query"));
});
Template.searchQuery.events({
'keyup .query' : function (event, template) {
query = template.find('.query').value
Session.set("query", query);
}
});
Template.searchResults.results = function () {
return _get(Session.get("query"));
}
}
if (Meteor.isServer) {
Meteor.startup(function() {
if (Animals.find().count() === 0) {
Animals.insert({name: "panda", is_active: true, id_species: 'bear'});
Animals.insert({name: "panda1", is_active: true, id_species: 'bearOther'});
Animals.insert({name: "panda2", is_active: true, id_species: 'bear'});
Animals.insert({name: "panda3", is_active: true, id_species: 'bearOther'});
}
});
Meteor.publish("animals", _get);
}