I am new to Javascript and Meteor and having some trouble getting the Meteor autocomplete package from Mizzau to work correctly. I can get the form to autocomplete just fine, but having trouble getting it to filter my todos. The end result I am hoping for is to enter in a todo into the autocomplete and have it filter the subscription, I would also settle for search and going from there. I will also say my initial state is the list returns 0 todos (none are displayed) I feel like I may be close. A good part of my code came from this: Meteor - autocomplete with "distinct" feature?
T
Does it have something to do with my subscription?
Here is my server side publish call:
Meteor.publish("todosAuto", function(selector, options) {
Autocomplete.publishCursor(Todos.find(selector, options), this);
this.ready();
});
My client side subscription:
Meteor.subscribe('todosAuto');
The relevant part of my template:
<div class="container todoFormSec">
<div class="col-md-4">
{{> inputAutocomplete settings=settings id="msg" class="form-control" placeholder="Search..."}}
</div>
<div class="row">
<div class="col-md-5 pull-right">
<h1 class="todocountstyle text-right">You Have {{ todoCount }} Todos</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="todos">
{{ #each todosAuto }}
{{ >todo }}
{{ /each }}
</div>
</div>
</div>
</div>
And my settings:
Template.home.helpers({
todos: function() {
return Todos.find();
},
todoCount: function() {
return Todos.find({userid: Meteor.userId()}).count();
},
settings: function() {
return {
position: "top",
limit: 5,
rules: [
{
token: '#',
collection: 'Todos',
field: "title",
subscription: 'todosAuto',
template: Template.titlePill
},
{
token: '#',
collection: 'Todos',
field: "categories",
options: '',
subscription: 'todosAuto',
matchAll: true,
template: Template.dataPiece
}
]
};
}
});
Template.home.events({ // listen for selection and subscribe
"autocompleteselect input": function(event, template, doc) {
Meteor.subscribe("todosAuto", doc.title);
}
});
In the past I tried to use this autocomplete package you are having trouble with. I found it just wasn't high fidelity enough for my needs. Therefore I recommend Twitter typeahead and bloodhound to you. I am very happy with the following packages ajduke:bootstrap-tokenfield in combination with sergeyt:typeahead
The time investment is well worth it. See my previous posting for examples. Here are more examples.
If the above is too complicated, try jeremy:selectize. Point is that there are plenty of better packages out there.
Related
Objective: I have a form interface that is being loaded with an object's current data for editing. The user opens this modal with the form that is loaded with the current info so they an either edit it or leave it
Currently working: The form loads with the data from my three objects (details, editSubEvents, instructions) and shows properly without issue
My problem: When I edit the fields and hit submit, I'm only currently dumping the submitted data object to make sure I have what I need. I get the eventID fine becasue it won't change and I get it from the original object. However, I need to store the new title, instruction, and subEvents (as an array) in order to submit them because they're obviously different from the origin ones
How can I properly store the new info from these input fields, including storing the new subEvent title and instructions as an array?
<div class="modal-body">
<div class="form-group row" v-for="detail in details">
<p class="modal-title">Title</p>
<input v-model="detail.title" type="text" class="form-control" id="EventTitle" name="EventTitle">
</div>
<div class="form-group row" v-for="subEvent in editSubEvents">
<p class="modal-title">SubEvent Title</p>
<input v-model="subEvent.title" type="text" class="form-control" id="newSubTitle" name="newSubTitle">
<p class="modal-title">SubEvent Instructions</p>
<textarea v-model="subEvent.instructions" type="text" class="form-control" id="newSubInstructions" name="newSubInstructions"></textarea>
</div>
</div>
data() {
return {
details: [],
instructions:[],
editSubEvents:[],
}
},
methods: {
updateEvent() {
let data = {
EventID: this.details[0].event_id,
title:
origin:
instructions:
subEvents: //needs to be an array
};
console.dir(data);
}
}
All of the properties of your data object can be bound to the UI elements (and most of them are, going by your template example code). The properties of the data object are accessible through the Vue component's this.
new Vue({
el: '#vueApp',
data() {
return {
details: [],
instructions:[],
editSubEvents:[],
}
},
methods: {
updateEvent() {
const data = {
EventID: this.details[0].event_id,
title: this.details[0].title,
origin: this.details[0].origin,
instructions: this.instructions,
subEvents: this.subEvents,
};
console.dir(data);
}
}
}
I'm working on an Emberjs application and I've got quite far with it
but i'm having an issue and I think that I've looked at every corner in the
web without finding the solution
Now my problem is that I have a dropdown that queries record on change "meaning" I have a "Dental" Department which contains "Braces" as a service
(service belongs to department) so when the user changes the dropdown option a query runs to filter the results again but within the results showing there is a text field which should be able to allow the user to search within the services shown accordingly to the selected department.
So far so good. The problem is that when the user starts typing to filter the data the condition in which services belongs to the selected department won't work any more so is there a way to use AND in my "Ember" controller to query records with more than one condition ?
Here is my Template
<div class="form-group">
{{#power-select
options=departments
selected=selectedDepartment
searchField="name"
placeholder="Select Department..."
onchange=(action (mut selectedDepartment))
dropdownClass="in-modal-dropdown"
renderInPlace=true
as |department|
}}
{{department.name}}
{{/power-select}}
</div>
{{#if selectedDepartment}}
<hr />
<div class="form-group has-feedback">
{{input value=searchText class="form-control input-sm" placeholder="Search Services" insert-newline="doSearch"}}
{{#if searchText}}
<i class="glyphicon glyphicon-remove form-control-feedback"></i>
{{/if}}
</div>
<br />
{{#each departmentServices as |service|}}
<button {{action 'selectService' service}} class="ux-product-override-for-request w-clearfix w-inline-block">
<div class="ux-product-icon"></div>
<div class="ux-product-title">{{service.name}}</div>
<div class="ux-product-price">{{service.price}} RS</div>
</button>
{{/each}}
{{/if}}
and my Controller
store: Ember.inject.service(),
departments: Ember.computed(function(){
return this.get('store').findAll('department')
}),
departmentServices: Ember.computed('selectedDepartment', 'search', function(){
if(this.get('search') == '' || this.get('search') == null){
console.log(this.get('search'));
return this.get('store').query('service', {
where: {
department: this.get('selectedDepartment.id')
}
})
} else {
return this.get('store').query('service', {
where: {
{ department: { this.get('selectedDepartment.id')} }
{ name: { contains: this.get('search')} }
}
})
}
}),
selectedDepartment: null,
{{input value=searchText - here you are using searchText but in departmentServices computed property you are using search but this is not the actual issue.
Issue is, this.get('store').query will return the Promise not the value so your implementation will not work out.(if you want to make it work you can try 3rd options Special promise-backed objects mentioned https://emberigniter.com/guide-promises-computed-properties/)
I will encourage you to introduce setDepartmentServices function which will query and update departmentServices property. and power-select for onchange instead of using the mut you can use onchange = (action 'setSelectedDepartment') and searchText input filed doSearch will call setDepartmentServices.
Here is the pseudo code,
setDepartmentServices() {
//this will do query and will set the result in departmentServices property.
}
actions: {
setSelectedDepartment(selectedDepartment) {
this.set('selectedDepartment', selectedDepartment);
//check if its ok to update departmentServices
this.send('setDepartmentServices');
}
doSearch() {
//check if its ok to update departmentServices
this.send('setDepartmentServices');
}
}
I am new to meteor.Iam using meteor aldeed autoform and collection2 packages in my app.here is my client js file.
Schema = {};
Schema.dc_address = new SimpleSchema({
'dataCenterName': {
type: String,
index: 1,
label:'Name of the Provider',
regEx: /^[a-zA-Z\s]+$/
},
'address1': {
type: String,
index: 1,
label:'Address Line 1',
regEx: /^[a-zA-Z0-9\s]+$/
},
'address2': {
type: String,
index: 1,
label:'Address Line 2',
regEx: /^[a-zA-Z0-9\s]+$/
},
});
Template.dataCenters.helpers({//dataCenters is my main template
steps: function() {
return [{
id: 'dc_address',
title: 'Name & Address',
template: 'dc_address',
formId: 'dc_address_form',
onSubmit: function(data, wizard) {
var params=_.extend(wizard.mergedData(), data);
alert(params);
var jsonrpc = new $.JsonRpcClient({ ajaxUrl: 'http://172.16.4.190:8384' });
jsonrpc.call(
'dataCenterCreate', params,
function(result) {alert('Pizzeria answered: ' + $.toJSON(result)); },
function(error) { console.log('There was an error', $.toJSON(error)); }
);
}
}];
}
});
here is my html page
<template name="dc_address">
<div class="form-wrapper">
{{#autoForm doc=this.data id="dc_address_form" schema=Schema.dc_address }}
<div class="col-md-12">
{{> afQuickField name="dataCenterName" placeholder="Enter DataCenter Name"}}
</div>
<table>
<tr>
<td class="col-md-6">
{{> afQuickField name="address1" placeholder="#7 4th cross"}}
</td>
<div class="col-md-1"></div>
<td class="col-md-6">
{{> afQuickField name="address2" placeholder="ITPL-banglore"}}
</td>
</tr>
<button type="submit" class="btn btn-success btn-md pull-right">Next</button>
{{/autoForm}}
</div>
</template>
That works pretty well although - it's CLIENT side submit => it is not secure.
How do I implement it is in server side?
For security you should remove autopublish and insecure packages. Once you do this inserting anything into the databases will throw an error. Try Posts.insert({}) in the console to see the errors appear.
You get around this by adding allow and deny rules on your server (see the meteor docs for more on allow/deny rules). You can also use meteor methods using: Meteor.call(...) to insert docs into the database without having any allow rules set up. You'd have to do your own checks within the meteor method in this case.
I am fairly a newbie to ember.js. I currently working on a school project which is essentially a message board (forum) application that allows users to add posts with comments.
My application contains three models: courses, messages, comments
course->hasMany->messages->hasMany->comments
So far I have been able to view all the courses and related messages using filter query to my server. Adding new messages works fine also except that it is not updating the new message added to the screen.
Problem: It is only when I refresh the page the new message I added is displayed.
App.Router.map(function() {
this.resource('home', { path : '/'}, function() {
this.resource('mycourse', { path : ':course_id' } );
});
});
App.MycourseRoute = Ember.Route.extend({
model: function(params) {
// the model for this route is a new empty Ember.Object
var string = '{"filters":[{"name":"courseid","op":"eq","val":'+params.course_id+'}]}'
return this.store.find('message', { q: string });
}
});
App.HomeRoute = Ember.Route.extend(
{
model: function() {
return this.store.find('course');
}
});
Here is my message controller:
App.MycourseController = Ember.ArrayController.extend({
actions: {
addMessage: function(messageText) {
var message = messageText;
var messageAdd =this.store.createRecord('message', {
message: message,
posttime: "12:00pm",
courseid: 4,
userid: 1
});
messageAdd.save();
}
}
});
My html part:
<script type="text/x-handlebars" id="home">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
{{#each}}
<li>{{#link-to 'mycourse' this.id}}{{name}}{{/link-to}}</li>
{{/each}}
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Subscribed Courses:</h1>
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" id="mycourse">
<button class="btn btn-default" type="button" id="create-message" {{action "addMessage" messageTxt}}>
Post!
</button>
{{input type="text" value=messageTxt}}
<br><br>
{{#each}}
<b>{{message}}</b>
<li>{{posttime}}</li>
<li>User name: {{user.username}}</li>
<li>Course name: {{course.alt_name}}</li>
<h4>Comments:</h4>
{{#each comments}}
<li>{{comment}}</li>
{{/each}}
<br>
{{/each}}
</script>
Turns out when you use findQuery (which I believe is the same as using find with query parameters), Ember does not return a live updating array, whereas it does for a straight up find/findAll. See this question on that exact issue that I asked a while back.
The solution here (adapted from kingpin2k's answer to said question) is to use filter to trick Ember into auto-updating:
App.MycourseRoute = Ember.Route.extend({
model: function(params) {
// the model for this route is a new empty Ember.Object
var string = '{"filters":[{"name":"courseid","op":"eq","val":'+params.course_id+'}]}'
return this.store.find('message', { q: string });
},
setupController:function(controller, model){
var filter = this.store.filter('color', function(color){
return model.contains(color);
});
this._super(controller, filter);
}
});
I have an Ember.js (1.0.0) Application for which I am trying to implement the built-in Ember.Select view.
This piece of the application shows three lists of tasks: inProgress, completed, and unassigned. The user can filter the tasks shown by their corresponding project. This is where the Ember.Select view comes in. However, when I load the route, Ember barks at me about the type of value I am giving it:
Assertion failed: The value that #each loops over must be an Array. You passed projects.all
Uncaught TypeError: Object projects.all has no method 'addArrayObserver'
Uncaught Error: Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.
I have been wrestling with this for hours, trying different permutations of the code below - and I know I must be missing something obvious, because it just can't be this difficult to get such a simple component to work properly. Hoping you guys can point me in the right direction.
Here is my Route:
Bee.TasksIndexRoute = Bee.Auth.Route.extend
setupController: (ctrl) ->
# get tasks
Bee.Auth.send
url: Bee.endpoint "/tasks"
.done (tasks) ->
ctrl.set "tasks.all", tasks
# get projects
Bee.Auth.send
url: Bee.endpoint "/projects"
.done (projects) ->
ctrl.set "projects.owned", projects.owned
ctrl.set "projects.participating", projects.participating
ctrl.set "projects.all", projects.owned.concat projects.participating
Here is my Controller:
Bee.TasksIndexController = Ember.ObjectController.extend
project: null
content:
tasks:
all: []
inProgress: []
completed: []
unassgined: []
projects:
all: []
owned: []
participating: []
visible: (->
ctrl = #
# filter tasks here
).property "project"
Here is my Template:
<script type="text/x-handlebars" id="tasks/index">
<div class="center-pane">
<div class="top_options">
<div class="project_filter">
<strong>Viewing: </strong>
{{view Ember.Select
content=projects.all
optionValuePath='content._id'
optionLabelPath='content.title'
value=project
prompt='All Tasks'
}}
</div>
<strong class="gold-gradient option_button">
{{#link-to 'tasks.create' classNames='new_task'}}Create Task{{/link-to}}
</strong>
</div>
<div class="col3">
<div class="col-header in-progress light-gradient">
<h3>In Progress</h3>
</div>
<div id="tasks_active_list">
{{#if visible.inProgress.length}}
<ul>{{#each visible.inProgress}}{{view Bee.TaskListView}}{{/each}}</ul>
{{else}}
<p class="no_projects">None</p>
{{/if}}
</div>
</div>
<div class="col3">
<div class="col-header completed light-gradient">
<h3>Completed</h3>
</div>
<div id="tasks_closed_list">
{{#if visible.completed.length}}
<ul>{{#each visible.completed}}{{view Bee.TaskListView}}{{/each}}</ul>
{{else}}
<p class="no_projects">None</p>
{{/if}}
</div>
</div>
<div class="col3">
<div class="col-header unassigned light-gradient">
<h3>Unassigned</h3>
</div>
<div id="tasks_unassigned_list">
{{#if visible.unassigned.length}}
<ul>{{#each visible.unassigned}}{{view Bee.TaskListView}}{{/each}}</ul>
{{else}}
<p class="no_projects">None</p>
{{/if}}
</div>
</div>
</div>
</script>
Any insight will be much appreciated. I do know that the Ember.Select is the culprit, since when I replace it with a simple:
<select>
{{#each projects.all}}
<option value="{{_id}}">{{title}}</option>
{{/each}}
</select>
... it renders fine - however I need to use the Ember.Select so I can bind the value to the project property on the TasksIndexController - since I will use that as an observable for firing the visible function.
try setting projects.all to null up front. maybe ember select has an issue with the pojo default array on the class.
Bee.TasksIndexController = Ember.ObjectController.extend
project: null
content:
tasks:
all: []
inProgress: []
completed: []
unassgined: []
projects:
all: null
owned: []
participating: []
visible: (->
ctrl = #
# filter tasks here
).property "project"
setupController: (ctrl) ->
# get tasks
Bee.Auth.send
url: Bee.endpoint "/tasks"
.done (tasks) ->
ctrl.set "tasks.all", tasks
# get projects
Bee.Auth.send
url: Bee.endpoint "/projects"
.done (projects) ->
ctrl.set "projects.owned", projects.owned
ctrl.set "projects.participating", projects.participating
ctrl.set "projects.all", projects.owned.concat projects.participating
Here's a simplified example: http://emberjs.jsbin.com/aletIyU/3/edit