I'm wondering if this is possible or not. When the user hits the save button, I want knockout to check if the field labeled Status has been changed to Completed - then I want it to enter the current date into the Date Completed field.
Here are my fields -
<ul class="button-group">
<li><button data-bind="click: save" class="success">Save</button></li>
<li><button data-bind="click: saveAndClose" class="success">Save and close</button></li>
<li><button data-bind="click: cancel" class="alert">Cancel</button></li>
</ul>
<div data-bind="with: item">
<label for="Type">Type</label>
<input id="Type" data-bind="value: Type" disabled="disabled" type="text" />
<label for="Status">Status</label>
<select id ="Status" data-bind="value: Status">
<option value="Not Started">Not Started</option>
<option value="In Progress">In Progress</option>
<option value="Completed">Completed</option>
</select>
<label for="Subject">Subject</label>
<input id="Subject" data-bind="value: Subject" type="text"/>
<label for="Content">Content</label>
<textarea id="Content" data-bind="value: Content" type="text"></textarea>
label for="DateCreated">Date Created (DD/MM/YYYY)</label>
<input id="DateCreated" disabled data-bind="valueFormat: DateCreated, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
<label for="DateLastModified">Date Last Modified (DD/MM/YYYY)</label>
<input id="DateLastModified" data-bind="valueFormat: DateLastModified, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
<label for="DateCompleted">Date Completed (DD/MM/YYYY)</label>
<input id="DateCompleted" data-bind="valueFormat: DateCompleted, type: 'datetime', format: 'DD/MM/YYYY'" type="text" placeholder="Enter date in format DD/MM/YYYY" />
</div>
And heres what my js file consists of so far
var Module = function(){
var self = this;
var updateItem = function(item) {
if (item) {
self.setupEntityValidation(item, self);
self.item(item);
}
};
self.title = ko.observable();
self.item = ko.observable();
self.isLoadingData = ko.observable(true);
self.entityName = 'Task';
self.entityId = null;
self.activate = function(cid, idOrNew, newType) {
var loadedItem,
types = {
task: {
type: 'Task',
newStatus: 'Not Started'
},
phone: {
type: 'Phone',
newStatus: 'Completed'
},
email: {
type: 'Email',
newStatus: 'Completed'
},
note: {
type: 'Note',
newStatus: 'Completed'
}
},
now = null,
mode = 'new' === idOrNew ? 'Create new' : 'Edit';
// Page title
self.entityId = 'new' === idOrNew ? 0 : parseInt(idOrNew);
self.title(mode + ' task');
if ('new' !== idOrNew) {
// Load the item
self.isLoadingData = ko.observable(true);
ds.getEntityWithKey('Task', self.entityId)
.then(function(data) {
if (data && data.entity) {
// Load item
updateItem(data.entity);
} else {
log.error('#todo get by id failed with result', data);
}
})
.fail(function(err) {
log.error('#todo get by id failed completely', err.stack);
})
.finally(function() {
self.isLoadingData(false);
});
} else {
// No id, create new. Check newType is valid
if (types.hasOwnProperty(newType)) {
// Create new task
now = new Date();
loadedItem = ds.createEntity('Task', {
CentreID: parseInt(cid),
Type: types[newType].type,
Status: types[newType].newStatus,
DateCreated: now.toISOString()
});
if (loadedItem) {
updateItem(loadedItem);
} else {
log.error('Could not create new task item');
}
} else {
log.error('Cannot create new task, illegal type:' + newType);
}
self.isLoadingData(false);
}
};
};
var moduleInstance = new Module();
modex.addComponent('EntitySaveCancel', moduleInstance);
modex.addComponent('EntityValidation', moduleInstance);
return moduleInstance;
});
If you want to instantly apply the change when the field changes to "Completed" you can add a subscribe function that watches the observable "Status" for any change:
self.Status.subscribe(function (value) {
if (value === "Completed") {
//Change date here.
}
});
If you want to change it upon clicking save, you can check "Status" observable value there and set the date accordingly.
Please let us know if this works with you.
Related
I have an array with the students.
I have the implementation of the addition of students.
Question: how to clean up after pressing the field? Fields must be cleaned so that when you try to enter new values were not set to the old values.
Tried everything, nothing works. Neither the <form> -> <button type = "reset">, or the selectors ...
What can be done to solve this problem?
index.html
......
<!-- add new student -->
<br>
<input v-model="students.name" placeholder="surname">
<select v-model="students.group">
<option value="1">1</option>
<option value="2">2</option>
</select>
<input v-model="students.year" placeholder="Bitrh year">
<input type="checkbox" v-model="students.done">
<label>done</label>
<input v-model.number="students.mark" type="number" placeholder="mark">
<button type="reset" #click="addStudent()">add to array</button>
</div>
<!-- /add new student -->
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="/index.js"></script>
index.js
let students = [
{
id: '1',
name: "Test",
group: "1",
year: "1985",
done: true,
mark: 4,
},
]
var app = new Vue ({
el: '#app',
data: {
students: [],
search: '',
stud: students.slice(),
},
methods: {
deleteStudent(studId) {
this.stud = this.stud.filter(elem => {
return elem.id != studId;
});
},
addStudent() {
const id = this.stud.length + 1;
this.stud.push({ id, ...this.students });
}
}
})
I don't know vue, but you can always select all inputs and set it's value on '' :
document.querySelectorAll('input').forEach(input => input.value='')
in best case apply it to container so sth like that:
document.querySelector('.formClassName').querySelectorAll('input').forEach(input => input.value='')
Just use following:
deleteStudent(studId) {
this.stud.splice(students.id, 1)
}
You can splice something based on it's id the 1 after the comma is that it deletes 1 stud-data from your id.
When you want to use a v-model on your form and let the user enter some data, you should pass an initial object to your inputs. And when the user submits the form, you'll push that data to your array, following to reset your initial object.
So this implementation will help you:
<!-- add new student -->
<br>
<input v-model="initialState.name" placeholder="surname">
<select v-model="initialState.group">
<option value="1">1</option>
<option value="2">2</option>
</select>
<input v-model="initialState.year" placeholder="Bitrh year">
<input type="checkbox" v-model="initialState.done">
<label>done</label>
<input v-model.number="initialState.mark" type="number" placeholder="mark">
<button type="reset" #click="addStudent()">add to array</button>
</div>
<!-- /add new student -->
<script src="https://cdn.jsdelivr.net/npm/vue#2/dist/vue.js"></script>
<script src="/index.js"></script>
var app = new Vue ({
el: '#app',
data: {
students: [],
initialState: {
id: '',
name: '',
group: '',
year: '',
done: true,
mark: 0
},
search: '',
},
methods: {
deleteStudent(studId) {
this.students = this.students.filter(elem => {
return elem.id != studId;
});
},
addStudent() {
const id = this.students.length + 1;
this.students.push({ id, this.initialState });
this.initialState = JSON.parse(JSON.stringify({
id: '',
name: '',
group: '',
year: '',
done: true,
mark: 0
}));
}
}
})
My html code is
I also need to add sez which is in array format and also i need to add multiple images, need to provide add image and when clicking on it, need to add images as needed by the client
<form method="POST" enctype="multipart/form-data" v-on:submit.prevent="handleSubmit($event);">
<div class="row">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Name</label>
<input type="text" class="form-control" v-model="name">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Alias</label>
<input type="text" class="form-control" v-model="alias">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Sex</label>
<select class="form-control" v-model="sex" id="level">
<option value="Male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
</div>
<div class="row" v-for="(book, index) in sez" :key="index">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Date </label>
<input type="date" class="form-control" v-model="book.date">
</div>
</div>
<div class="col-md-8">
<div class="form-group label-floating">
<label class="control-label"> Details</label>
<input type="text" class="form-control" book.details>
</div>
</div>
</div>
<a #click="addNewRow">Add</a>
<div class="card-content">
<div class="row">
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Signature</span>
<label class="custom-file-upload"><input type="file" name="photo" accept="image/*" />
</label>
</div>
</div>
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
</div>
</div>
</form>
My vue js code is
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null,
}, ],
photo: '',
sign: '',
},
methods: {
addNewRow: function() {
this.seziure.push({
date: null,
details: null,
});
},
handleSubmit: function(e) {
var vm = this;
data = {};
data['sez'] = this.sez;
data['name'] = this.name;
data['alias'] = this.alias;
data['sex'] = this.sex;
//how to add images
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success")
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed")
}
}
});
return false;
},
},
});
This is my code. I have no idea about how to add images in this case.
Can anyone please help me pass this data.
How to pass this data along with images to the backend?
I don't want to use base64 encoding. I need to just pass this image in this ajax post request along with other data
Using axios:
Template
...
<input type="file" name="photo" accept="image/*" #change="setPhotoFiles($event.target.name, $event.target.files) />
...
Code
data () {
return {
...
photoFiles: [],
...
}
},
...
methods: {
...
setPhotoFiles (fieldName, fileList) {
this.photoFiles = fileList;
},
...
handleSubmit (e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
...
this.photoFiles.forEach((element, index, array) => {
formData.append('photo-' + index, element);
});
axios.post("http://localhost:4000/save/", formData)
.then(function (result) {
console.log(result);
...
}, function (error) {
console.log(error);
...
});
}
}
I'm not sure where would you like the extra images to appear, but I added them after this column:
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
And here's the column I added — "add images": (You can try this feature here, with the updates)
<div class="col-md-4">
<ul class="list-group" :if="images.length">
<li class="list-group-item" v-for="(f, index) in images" :key="index">
<button class="close" #click.prevent="removeImage(index, $event)">×</button>
<div class="button success expand radius">
<label class="custom-file-upload">
<input type="file" class="images[]" accept="image/*" #change="previewImage(index, $event)">
</label>
</div>
<div :class="'images[' + index + ']-preview image-preview'"></div>
</li>
</ul>
<button class="btn btn-link add-image" #click.prevent="addNewImage">Add Image</button>
</div>
And the full Vue JS code (with jQuery.ajax()):
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null
}],
// I removed `photo` and `sign` because (I think) the're not necessary.
// Add I added `images` so that we could easily add new images via Vue.
images: [],
maxImages: 5,
// Selector for the "Add Image" button. Try using (or you should use) ID
// instead; e.g. `button#add-image`. But it has to be a `button` element.
addImage: 'button.add-image'
},
methods: {
addNewRow: function() {
// I changed to `this.sez.push` because `this.seziure` is `undefined`.
this.sez.push({
date: null,
details: null
});
},
addNewImage: function(e) {
var n = this.maxImages || -1;
if (n && this.images.length < n) {
this.images.push('');
}
this.checkImages();
},
removeImage: function(index) {
this.images.splice(index, 1);
this.checkImages();
},
checkImages: function() {
var n = this.maxImages || -1;
if (n && this.images.length >= n) {
$(this.addImage, this.el).prop('disabled', true); // Disables the button.
} else {
$(this.addImage, this.el).prop('disabled', false); // Enables the button.
}
},
previewImage: function(index, e) {
var r = new FileReader(),
f = e.target.files[0];
r.addEventListener('load', function() {
$('[class~="images[' + index + ']-preview"]', this.el).html(
'<img src="' + r.result + '" class="thumbnail img-responsive">'
);
}, false);
if (f) {
r.readAsDataURL(f);
}
},
handleSubmit: function(e) {
var vm = this;
var data = new FormData(e.target);
data.append('sez', this.sez);
data.append('name', this.name);
data.append('alias', this.alias);
data.append('sex', this.sex);
// The `data` already contain the Signature and Recent Photograph images.
// Here we add the extra images as an array.
$('[class~="images[]"]', this.el).each(function(i) {
if (i > vm.maxImages - 1) {
return; // Max images reached.
}
data.append('images[' + i + ']', this.files[0]);
});
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success");
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed");
}
},
cache: false,
contentType: false,
processData: false
});
return false;
},
},
});
Additional Notes
I know you're using Node.js in the back-end; however, I should mention that in PHP, the $_FILES variable would contain all the images (so long as the fields name are properly set); and I suppose Node.js has a similar variable or way of getting the files.
And in the following input, you may have forgotten to wrap book.details in v-model:
<input type="text" class="form-control" book.details>
<input type="text" class="form-control" v-model="book.details"> <!-- Correct -->
UPDATE
Added feature to limit number of images allowed to be selected/uploaded, and added preview for selected image. Plus the "send images as array" fix.
If you're using HTML5, try with a FormData object ; it will encode your file input content :
var myForm = document.getElementById('addForm');
formData = new FormData(myForm);
data: formData
Use below templete to show/upload the image:
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onImageUpload">
</div>
<div v-else>
<img :src="image" />
<button #click="removeImage">Remove image</button>
</div>
Js code:
data: {
image: '',
imageBuff: ''
},
methods: {
onImageUpload(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
var image = new Image();
var reader = new FileReader();
this.imageBuff = file;
reader.onload = (e) => {
this.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function(e) {
this.image = '';
},
handleSubmit(e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
formData.append('image', this.imageBuff);
...
// Ajax or Axios can be used
$.ajax({
url: 'http://localhost:4000/save/',
data: formData,
processData: false, // prevent jQuery from automatically transforming the data into a query string.
contentType: false,
type: 'POST',
success: function(data) {
console.log(data);
...
}
});
}
}
I'm having trouble getting started with binding a Form to a remote Datasource in Kendo UI for javascript
I have verified that the ajax call returns the correct JSONP payload, e.g:
jQuery31006691693527470279_1519697653511([{"employee_id":1,"username":"Chai"}])
Below is the code:
<script type="text/javascript">
$(document).ready(function() {
var viewModel = kendo.observable({
employeeSource: new kendo.data.DataSource({
transport: {
read: {
url: baseUrl + "/temp1",
dataType: "jsonp"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
return options;
}
},
batch: true,
schema: {
model: {
id: "employee_id",
fields:{
employee_id: { type: "number" },
username: { type: "string" }
}
}
}
}),
hasChanges: false,
save: function() {
this.employeeSource.sync();
this.set("hasChanges", false);
},
change: function() {
this.set("hasChanges", true);
}
});
kendo.bind($("#item-container"), viewModel);
viewModel.employeeSource.read();
});
</script>
<div id="item-container">
<div class="row">
<div class="col-xs-6 form-group">
<label>Username</label>
<input class="form-control k-textbox" type="text" id="username" data-bind="value: username, events: { change: change }" />
</div>
</div>
<button data-bind="click: save, enabled: hasChanges" class="k-button k-primary">Submit All Changes</button>
</div>
No errors are thrown, but I was expecting my username text form field to be populated with the value 'Chai', and so on.. but it doesn't
Your textbox is bound to a username property but this doesn't exist on your view-model, nor is it being populated anywhere. Assuming your datasource correctly holds an employee after your call to read(), you will need to extract it and set it into your viewmodel using something like this:
change: function(e) {
var data = this.data();
if (data.length && data.length === 1) {
this.set("employee", data[0]);
this.set("hasChanges", true);
}
}
And modify the binding(s) like this:
<input class="form-control k-textbox" type="text" id="username"
data-bind="value: employee.username, events: { change: change }" />
You should also be aware that the change event is raised in other situations, so if you start using the datasource to make updates for example, you'll need to adapt that code to take account of the type of request. See the event documentation for more info. Hope this helps.
I have a list of start and end page numbers using angularJS forms. What i want to do is...for example if a user has entered the end page to be 4 on the first row, then I want the start page of the second row to be automatically updated with 5 (+1 of the previous end page).
I'm using an object that looks like this:
$scope.pages = {
items: [{
startNumber: 1,
endNumber: ''
},
{
startNumber: '',
endNumber: ''
},
{
startNumber: '',
endNumber: ''
},
{
startNumber: '',
endNumber: ''
}
]
};
HTML:
<div class="form-group col-sm-3" ng-repeat="file in pages.items">
<label for="start">Pages </label>
<input type="number" name="startPage" class="form-control" id="start" ng-model="file.startNumber">
<label for="end"> - </label>
<input type="number" name="endPage" class="form-control" id="end" ng-model="file.endNumber">
</div>
Function:
$scope.autoStartPageNumber = function(endPage) {
if (endPage.length) {
startNumber = endNumber + 1;
}
};
I'm not sure if i'm using the function correctly or where to put the function to add the numbers. If anyone has done anything similar to this..any help would be great
You can use ng-change on second input field and update the field accordingy. You can do something like this.
$scope.autoStartPageNumber = function(index) {
if (index + 1 < $scope.pages.items.length) {
$scope.pages.items[index + 1].startNumber = 1 + $scope.pages.items[index].endNumber;
}
};
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.pages = {
items:[
{
startNumber:1,
endNumber:''
},
{
startNumber:'',
endNumber:''
},
{
startNumber:'',
endNumber:''
},
{
startNumber:'',
endNumber:''
}
]
};
$scope.autoStartPageNumber = function (index) {
if(index +1 < $scope.pages.items.length){
$scope.pages.items[index+1].startNumber=$scope.pages.items[index].endNumber + 1;
}
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="form-group col-sm-3" ng-repeat="file in pages.items">
<label for="start">Pages </label>
<input type="number" name="startPage" class="form-control" id="start" ng-model="file.startNumber">
<label for="end"> - </label>
<input type="number" name="endPage" class="form-control" id="end" ng-model="file.endNumber" ng-change="autoStartPageNumber($index)">
</div>
</div>
New Meteor User.
Wanting to modify the leaderboard example for a story sizing tool where members in a team can rate a story simultaneously.
Very similar to leaderboard, but want to add a flag/event/button for an admin user to be able to turn on and off the leaderboard displayed.
Here is my feeble attempt at this -
// Set up a collection to contain member information. On the server,'
// it is backed by a MongoDB collection named "members".
Members = new Meteor.Collection("members");
Flags = new Meteor.Collection("Flags");
if (Meteor.isClient) {
Meteor.startup(function() {
Session.set("viewall", false);
});
Template.leaderboard.members = function () {
if (Session.get("viewall"))
{
return Members.find({}, {sort: {score: -1, name: 1}});
}
};
Template.size.members = function() {
return Members.find({}, {sort: {name: 1}});
};
Template.size.events ({
'click input.submit': function(){
var memname = document.getElementById('select_member').value;
//alert(memname);
var member = Members.findOne({_id: memname});
if(member._id)
{
Session.set("selected_player", member._id);
//alert(member.name);
}
var memsize = document.getElementById('select_size').value;
alert(memsize);
Members.update(Session.get("selected_player"), {$set: {score: memsize}});
}
});
Template.leaderboard.isAdmin = function() {
var member=Members.findOne(Session.get("selected_player"));
var memtype = member.utype;
if (memtype=== "admin")
{
return true;
}
else
{
return false;
}
};
Template.leaderboard.selected_name = function () {
var member = Members.findOne(Session.get("selected_player"));
return member && member.name;
};
Template.leaderboard.viewAll = function() {
var flag = Flags.findOne({name:"showAll"});
if (flag)
{
alert("View All flag set for current user : " + flag.value);
return flag && flag.value;
}
else return false;
};
Template.leaderboard.selected_size = function () {
var member = Members.findOne(Session.get("selected_player"));
return member && member.score;
};
Template.member.selected = function () {
return Session.equals("selected_player", this._id) ? "selected" : '';
};
Template.leaderboard.events({
'click input.inc1': function () {
alert('setting it to 1');
updatePrevScore();
// Members.find({_id: Session.get("selected_player")}).foreach(function(doc){
// doc.prev_score = doc.score;
// Member.save(doc);
// });
//Members.update(Session.get("selected_player"), {$set: {prev_score: score}});
Members.update(Session.get("selected_player"), {$set: {score: 1}});
},
'click input.inc2': function () {
updatePrevScore();
Members.update(Session.get("selected_player"), {$set: {score: 2}});
},
'click input.inc3': function () {
updatePrevScore();
Members.update(Session.get("selected_player"), {$set: {score: 3}});
},
'click input.inc5': function () {
updatePrevScore();
Members.update(Session.get("selected_player"), {$set: {score: 5}});
},
'click input.inc8': function () {
updatePrevScore();
Members.update(Session.get("selected_player"), {$set: {score: 8}});
},
'click input.inc13': function () {
updatePrevScore();
Members.update(Session.get("selected_player"), {$set: {score: 13}});
},
'click input.inc20': function(){
updatePrevScore();
Members.update(Session.get("selected_player"),{$set: {score:20}});
},
'click input.reset': function(){
if (confirm('Are you sure you want to reset the points?')) {
resetScores();
}
},
'click input.showAll': function() {
setFlag();
},
'click input.hideAll': function() {
resetFlag();
}
});
Template.member.events({
'click': function () {
Session.set("selected_player", this._id);
}
});
function resetFlag() {
Meteor.call("resetFlag", function(error, value) {
Session.set("viewall", false);
});
};
function setFlag() {
Meteor.call("setFlag", function(error, value) {
Session.set("viewall", true);
});
};
function resetScores() {
//alert('resetting scores');
Members.find().forEach(function (member) {
Members.update(member._id, {$set: {prev_score: member.score}});
Members.update(member._id, {$set: {score: 0}});
});
Session.set("selected_player", undefined);
};
function updatePrevScore() {
//alert('resetting scores');
Members.find().forEach(function (member) {
if (member._id === Session.get("selected_player"))
{
Members.update(member._id, {$set: {prev_score: member.score}});
Members.update(member._id, {$set: {score: 0}});
}
});
};
}
// On server startup, create some members if the database is empty.
if (Meteor.isServer) {
Members.remove({});
Meteor.startup(function () {
if (Members.find().count() === 0) {
var names = ["Member 1",
"Member 2",
"Member 3",
"Member 4",
"Member 5"
];
var type;
for (var i = 0; i < names.length; i++)
{
if (i===0)
type = "admin";
else
type="user";
Members.insert({name: names[i], score: 0, prev_score:0, utype:type});
}
}
else resetScores();
if (Flags.find().count() === 0) {
Flags.insert({name: "showAll", value: false});
}
else Flags.update({name:"showAll"}, {$set: {value:false}});
}
);
Meteor.methods({
setFlag: function() {
Flags.update({name:"showAll"}, {$set: {value:true}});
console.log("Updated flag to true");
return true;
},
resetFlag: function() {
Flags.update({name:"showAll"}, {$set: {value:false}});
console.log("Updated flag to false");
return false;
},
}
);
HTML =>
<head>
<title>Story Points Exercise</title>
</head>
<body>
<div id="story_id">
Story Sizing for Story ID: 78972
</div>
<div id="outer">
{{> leaderboard}}
</div>
</body>
<template name="size">
<div class="select_member">
<select id="select_member">
{{#each members}}
<option value={{_id}}> {{name}} </option>
{{/each}}
</select>
</div>
<div class="select_size">
<select id="select_size"> Select Size:
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=5>5</option>
<option value=8>8</option>
<option value=13>13</option>
<option value=20>20</option>
</select>
</div>
<div class="submitbutton">
<input type="button" class="submit" value="Submit" />
</div>
</template>
<template name="leaderboard">
<div class="leaderboard">
{{#if selected_name}}
<div class="details">
<div class="name">{{selected_name}}</div>
<div class="size">{{selected_size}}</div>
<div class="details">
<input type="button" class="inc1" value="1 points" />
<input type="button" class="inc2" value="2 points" />
<input type="button" class="inc3" value="3 points" />
<input type="button" class="inc5" value="5 points" />
<input type="button" class="inc8" value="8 points" />
<input type="button" class="inc13" value="13 points" />
<input type="button" class="inc20" value="20 points" />
</div>
{{#if isAdmin}}
<input type="button" class="showAll" value="showAll" />
<input type="button" class="hideAll" value="hideAll" />
<input type="button" class="reset" value="Reset"/>
{{/if}}
{{#if viewAll}}
{{#each members}}
{{> member}}
{{/each}}
{{/if}}
</div>
{{/if}}
{{#unless selected_name}}
{{>size}}
{{/unless}}
</div>
</template>
<template name="member">
<div class="member {{selected}}">
<span class="name">{{name}}</span>
<span class="score">{{score}}</span>
<span class="prevscore">{{prev_score}}</span>
</div>
</template>
Its working on one browser and one user (Admin type is able to enable the viewAll flag for the template to show all members.)
But, not working for mulitple users.
So, if I open a browser, select my name and a story size and I am the admin, I click Submit - I see buttons for changing the story size and to showAll, hideAll and Resetting the leaderbaord.
when I click on showAll, I as admin can see the leaderboard. But another user is not able to see the leaderboard. I verified that the change display event (showAll flag=true) is being received by that user's client.
Any ideas?
I was able to solve this by using a new collection called Views and observing for a specific document called showAll.
The showAll was set to be updated by the admin only.
It was hooked up to the template view with an {{#if}}.