I have been trying to make this work for several days now. I cannot access a profile object from its associated user object. I have the latest versions of Ember and ember-data
Ember-data: 1.0.0-beta15
Ember: 1.10.0 production
I have a simple table view that lists my users and a couple properties. Here is the view:
<script type="text/x-handlebars" data-template-name="users/verification-candidates">
<div class="small-12 column">
<h1>Candidates for Verification</h>
<table>
<tr>
<th>System ID</th>
<th>Email</th>
<th>Created At</th>
<th>Legal First Name</th>
<th>Legal Last Name</th>
<th></th>
<th></th>
</tr>
{{#each user in model itemController="candidate" }}
<tr>
<td> {{ user.id }}</td>
<td> {{ user.email }}</td>
<td>{{ user.created_at }}</td>
<td>{{ user.legal_first_name }}</td>
<td>{{ user.legal_last_name }}</td>
<td><button id="verify" {{ action "markVerified" }}>Verify</button></td>
<td><button id="disable" {{ action "markDisabled" }}>Disable</button></td>
</tr>
{{/each}}
</table>
</div>
</script>
The models are like so:
App.Profile = DS.Model.extend({
user: DS.belongsTo('user'),
incognito_name : DS.attr('string'),
advisor_id : DS.attr('number'),
created_at : DS.attr('date'),
//etc..
App.User = DS.Model.extend({
profile: DS.belongsTo('profile',{ async: true }),
email: DS.attr('string'),
sign_in_count: DS.attr('number'),
last_sign_in_at: DS.attr('date'),
//etc...
I am using the rest adapter:
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:1337',
defaultSerializer: 'json'
});
Pertinent routes:
App.Router.map(function(){
this.resource('users', { path: '/users'}, function(){
this.route('verification-candidates');
});
this.resource('profiles', { path: '/profiles' }, function(){
})
});
App.UsersRoute = Ember.Route.extend({
model: function(){
return this.store.find('user');
}
});
App.ProfilesRoute = Ember.Route.extend({
model: function(){
return this.store.find('profile');
}
})
App.UsersVerificationCandidatesRoute = Ember.Route.extend({
model : function(){
var items = this.store.find('user', { role: "advisor", disabled: false, is_verified: false });
return items;
},
})
My server is a sails.js back end, which accesses a database created by a Rails application.
I want to alter the profile in this object controller, but cannot access it in any meaningful form:
App.CandidateController = Ember.ObjectController.extend({
actions: {
markVerified: function(){
var user = this.get('model');
var profile = user.get('profile');
console.log(profile); //output 1
console.log(profile.incognito_name); //output 2
}
}
});
The output2 is undefined. Output 1 gives me some sort of object with properties __nextSuper, __ember_meta, a bunch of other things, isFulfilled, and content. But, no object properties from the model definition. This appears to be a promisearray,but, I thought this was the way to get a related object. Meanwhile, when I try to treat it as a PromiseArray, per the documentation, i get null, like this:
App.CandidateController = Ember.ObjectController.extend({
actions: {
markVerified: function(){
var user = this.get('model');
user.get('profile').then(function(content){
console.log("promise content is " + content);
//prints 'promise content is null'
})
//console.log(profile);
//console.log(profile.incognito_name);
}
}
I am fairly certain all my back end server/client things are in order, as I can access the user objects and work with them on the page. I am thinking it may be related to how the profile relates to the user via advisor_id, but, I am so confused right now. I am very much at my wit's end.
Related
app.component.ts
Debugger given the error that this.task is undefined
updateTodo(task: any){
this.todoService.updateData(task._id, this.task).subscribe(res => {
this.data= res;
console.log(res);
console.log(this.task);
});
}
app.service.ts
This is service file where the backend api are call in my angular app
updateData(id: any , data: any){
return this.httpClient.put('http://localhost:3000/todos/'+id, data);
}
app.component.html
This is the frontend of my app where the todos show and others user interface
<tbody>
<tr *ngFor="let todo of tasks ; let i = index">
<td>{{todo.todos}}</td>
<td> <input type="checkbox" (change)="updateTodo(todo)"[checked]="todo.isDone</td>
<td>
<button class="btn btn-danger btn-sm" id="del-btn"
(click)="deleteData(todo._id)">Delete</button>
</td>
</tr>
</tbody>
app.model.ts
This is model file
export class Todo {
_id:any;
todos:any;
isDone:any;
}
backend api
This is the backedn function which i created to update my todo
router.put('/:id' , async (req,res) => {
const id = req.params.id;
if(ObjectId.isValid(id)){
const todo = (req.body);
const todoUpdate = await Todo.findByIdAndUpdate(id ,{$set:emp}, {new:true});
res.status(200).json({code:200, message:'Todo Updated Successfully'});
}
else{
res.status(400).send('Todo Not Found By Given Id' + id);
}
});
I'm not sure if we understood each other, but you are passing the task as a parameter but then on two occasions you are trying to use the value of this.task. They are not the same thing and if this.task is not initialized then of course it will show that it's undefined.
updateTodo(task: any) {
console.log('task:', task); // Is the task correct?
this.todoService.updateData(task._id, task).subscribe(res => {
this.data = res;
console.log(res);
console.log(task); //not this.task
});
}
EDIT:
If the DB is not updated you might be sending incorrect data there. If there are no errors on Angular side you have to check the Back-End side.
I solve this question to add [(ngModel)]="todo.isDone" in my checkbox input filed
<tbody>
<tr *ngFor="let todo of tasks ; let i = index">
<td>{{todo.todos}}</td>
<td> <input type="checkbox" (change)="updateTodo(todo)" [(ngModel)]="todo.isDone</td>
<td>
<button class="btn btn-danger btn-sm" id="del-btn"
(click)="deleteData(todo._id)">Delete</button>
</td>
</tr>
And In my app.component.ts
updateTodo(task: any) {
this.todoService.updateData(task._id, task).subscribe(res => {
this.data = res;
console.log(res);
console.log(task);
});
}
I am using smart table in express template engine ejs. But I don't know how to get table data values at the time of editing table data.
I am using PUT method for updating the smart table data with the help of method-overriding. Without method-overriding PUT and DELETE are showing page not found error. I am unable to get updated data with PUT method from smart table.
var express = require('express');
var router = express.Router();
router.put('/edit/(:id)', function (req, res, next) {
console.log("edit data : ", req.body, req.params);
var device = { id: req.params.id }
req.getConnection(function (error, conn) {
conn.query('UPDATE users SET ? WHERE id = ' + req.params.id, device, function (err, result) {
if (err) {
res.redirect('/liveDevices')
} else {
res.redirect('/liveDevices')
}
})
})
})
<% liveDevices.forEach((data, i) => { %>
<tr>
<td name="sno"><%= ++i %></td>
<td><input class="no-edit" type="text" value=<%= data.device_id %> disabled /></td>
<td><input class="no-edit" type="text" value=<%= data.deviceTopic %> disabled /></td>
<td><span class="edit-row"><i class="fa fa-pencil mr-4" aria-hidden="true"></i>
<form method='POST' action='/liveDevices/edit/<%= data.device_id %>?_method=PUT'><button type="submit"><i
class="fa fa-check off mr-4" aria-hidden="true"></button></i></form>
</span><span><a href="/liveDevices/remove/<%= data.device_id %>"><i class="fa fa-trash"
aria-hidden="true"></i></a></span></td>
</tr>
<% }) %>
Actual output : edit data : {} { id: '9' }
Expected output : edit data : {If i click on edit button of smart table whose id=9 so it gives whole updated data values here in this block} {id : '9'}
I have a collection that has three fields: name(String), email(String) and appointments(Object)
I query the collection inside a router.get based on user email
router.get('/appointments', ensureAuthenticated, function(req, res, next) {
var query = {email: req.user.email};
PatientList.find(query, function(err, data){
if (err) throw err;
res.render('appointments', {data : data, title: 'Appointments'});
});
});
data from the query above looks like this:
{ __v: 0,
name: 'dan',
email: 'dan#gmail.com',
appointments:
[ { _id: 58373466542d6ae430a13337,
position: '1',
name: 'dan',
email: 'dan#gmail.com',
serviced: false,
hospital: 'Toronto hospital',
date: 'Thursday, November 24, 2016',
__v: 0 },
{ _id: 5837346a542d6ae430a13339,
position: '2',
name: 'dan',
email: 'dan#dan.com',
serviced: false,
hospital: 'Calgary hospital',
date: 'Thursday, November 24, 2016',
__v: 0 },
]
I want to access these fields inside the appointments field and display them on a table using handlebars. My html with handlebars looks like this
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>Clinic</td>
<td>Appointment Date</td>
<td>Patient Number</td>
<td>Clinic Queue Status</td>
</tr>
</thead>
<tbody>
{{#each data}}
<tr>
<td>{{this.appointments.hospital}}</td>
<td>{{this.appointments.date}}</td>
<td>{{this.appointments.position}}</td>
<td>{{#if this.appointments.serviced}}
Please return to the clinic immediately.
{{else}}
Patient is currently being served.
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
But it is not printing anything in the table
Passing properties to your view ( template ) via res.render results in those properties become available for use in your template.
You are passing a data property in your handlebars template, so you need to use your data variable inside, which is an object, that contains the appointments array.
In order to properly render them you need to use #each against data.appointments like :
{{#each data.appointments}}
<tr>
<td>{{hospital}}</td>
<td>{{date}}</td>
<td>{{position}}</td>
<td>{{#if serviced}}
Please return to the clinic immediately.
{{else}}
Patient is currently being served.
{{/if}}
</td>
</tr>
{{/each}}
Also keep in mind that when you use #each all of the properties of your array are served as locals for this block. So this. is not necessary anymore.
I would like to have multiple queries in a single router method as follows in my index.js file,
router.get('/users', function(req, res) {
var db = req.db;
var users = db.get('users');
var col_name=req.query.colname;
var col_value=req.query.colvalue;
var query={};
query[col_name]=col_value;
console.log(col_name);
console.log(col_value);
console.log(query);
//using this i would like to populate my dropdown list
users.distinct('symbol',{limit: 10000},function(e, syms){
res.send('users', {
title: 'usersSym',
'usersSym': syms
});
});
// using this I would populate a table in html
users.find(query,{limit: 10000},function(e, docs){
res.render('users', {
title: 'Users',
'users': docs
});
});
});
And in my .ejs file I'm trying to do the following :
<html>
<head>
//drop down list populating with first query
<select id="selected" name="colvalue" >
<option value="">--Select--</option>
<% usersSym.forEach(function(usersym) { %>
<option value="<%= usersym.symbol %>"><%= usersym.symbol %></option>
<% }); %>
</select>
//Table populating with second query
<table >
<tr >
<th>Symbol</th>
<th>Order_id</th>
</tr>
<tr>
<% users.forEach(function(user) { %>
<td ><%= user.symbol %></td>
<td><%= user.order_id %></td>
</tr>
<% }); %>
</table>
</body>
</head>
</html>
But no luck. Wondering whether I'm going in right direction or not. If not please guide me in right way.
// 1st fetch symbol
users.distinct('symbol',{limit: 10000},function(e, syms){
// 2nd fetch [users]
users.find(query,{limit: 10000},function(e, docs){
res.render('users',
{
usersSym: syms,
users: docs
}
);
});
});
// P.S. do not forget to check on error on each callback
You can only send data back to the client once. One way would be to do all those DB queries in a sequence, and then send all the data. Another might be to do it your way, check the status of all DB queries, and if all are done, then send the data.
I have a view with a table of products that can be added to a shopping cart. Each row has a DropDownList with allowed quantities that can be ordered along with a button to add to cart. Everything is populating and displaying properly. I know how to pass the item ID in the ActionLink but how can I get the value of the DownDownList associated with the table row of the ActionLink that was clicked?
I am guessing possibly using JQuery that fires when the ActionLink is clicked?
I also thought of making every row a form but that seems overkill.
Is there an easy MVC way to do this?
In prepping more info for a proper question and went ahead and solved it. Thank you Stephen for the nudge and info.
I tried putting a Html.BeginForm around each <tr> tag in the details section. This did indeed work for me. I was able to easily get the unique form info to POST for each individual row. However, when I would enable JQuery DataTables the submit would break. DataTables must be capturing the submit or click somehow. Haven't figured that out but it made me try JQuery which seems a much better way to do it.
Here is how I construct the table data row:
#foreach (var item in Model)
{
<tr>
<td>
<img src="#item.GetFrontImage()" width="100" />
</td>
<td>
<strong>#Html.DisplayFor(modelItem => item.DisplayName)</strong>
</td>
<td>
#Html.DisplayFor(modelItem => item.CustomerSKU)
</td>
<td>
#Html.DropDownList("OrderQty", item.GetAllowedOrderQuantities(), htmlAttributes: new { #class = "form-control" })
</td>
<td>
<a class="btn btn-default pull-right" data-id="#item.ID">Add to Cart</a>
</td>
</tr>
}
This creates a select with id of OrderQty and I embedded the item ID in data-id attribute of the link. I then used this JQuery to capture the info and POST it to my controller. Just have a test div displaying the results in this example:
// Add to Cart click
$('table .btn').click(function () {
// Gather data for post
var dataAddToCard = {
ID: $(this).data('id'), // Get data-id attribute (Item ID)
Quantity: $(this).parent().parent().find('select').val() // Get selected value of dropdown in same row as button that was clicked
}
// POST data to controller
$.ajax({
url: '#Url.Action("AddToCart","Shopping")',
type: 'POST',
data: JSON.stringify(dataAddToCard),
contentType: 'application/json',
success: function (data) { $('#Result').html(data.ID + ' ' + data.Quantity); }
})
});
The JQuery function receives the reference to the link being clicked so I can extract the Item ID from the data-id attribute. I can then get a reference to the dropdown (select) that is in the same row by using .parent.parent (gets me to the <tr> tag) and then just finding the next 'select' tag. Probably pretty obvious to a lot of you.
This works great for my purposes. I can also update other elements with data returned from the POST.
Thank you
Karl
for the table in html:
<div class="table-responsive">
<table id="employeeTable"class="table table-bordered">
<thead>
<tr>
<th class="text-center">ُُُEmpId</th>
<th class="text-center">Name</th>
<th class="text-center">Absense State</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#item.Id</td>
<td>#item.Name</td>
<td class="text-center">#Html.DropDownList("DDL_AbsentStatus", new SelectList(ViewBag.statusList, "Id", "Name"), new { #class = "form-control text-center" })</td>
</tr>
}
</tbody>
</table>
</div>
in javascript to get the selected value:
//Collect Date For Pass To Controller
$("#btn_save").click(function (e) {
e.preventDefault();
if ($.trim($("#datepicker1").val()) == "") {
alert("ادخل تاريخ يوم صحيح!")
return;
}
var employeesArr = [];
employeesArr.length = 0;
$.each($("#employeeTable tbody tr"), function () {
employeesArr.push({
EmpId: $(this).find('td:eq(0)').html(),
EntryDate: $.trim($("#datepicker1").val()),
StatusId: $(this).find('#DDL_AbsentStatus').val()
});
});
$.ajax({
url: '/Home/SaveAbsentState',
type: "POST",
dataType: "json",
data: JSON.stringify(employeesArr),
contentType: 'application/json; charset=utf-8',
success: function (result) {
alert(result);
emptyItems();
},
error: function (err) {
alert(err.statusText);
}
});
})