The correct way to display cards in lists, as in Trello - javascript

I'm trying to create project like Trello. I do not know how to do it properly.
I created function init in AngularJS Controller where i put http requests:
$scope.loadLists();
$scope.loadsCards();
Scripts:
$scope.loadLists = function () {
return ApiService.staff.list()
.then(function (resp) {
for (var i = 0; i < resp.length; i++) {
$scope.lists[i] = resp[i];
}
})
}
$scope.loadsCards = function () {
return ApiService.staff.cards()
.then(function (resp) {
for (var i = 0; i < resp.length; i++) {
$scope.cards = resp;
}
console.log($scope.cards)
})
}
I'm downloading tasks to $scope.cards
In console.log() we can see:
Array [ Object, Object, Object, Object, Object, Object, Object, Object ]
where the object consists of
var CardSchema = new Schema({
name: { type: String, maxlength: 20, required: true },
list: { type: Schema.Types.ObjectId, ref: 'List' },
updated: { type: Date, default: Date.now },
created: { type: Date, default: Date.now },
active: Boolean
});
And now I do not know what to do so that the cards are displayed only those in the given column that are assigned to the list. I mean : task.list == list._id
for the moment I did it
<div ng-repeat="list in lists track by $index">
<div style="float: left; margin-left: 5px;">
<div id="tasks">
<h3>{{list.name}}</h3>{{$index}}
<ul>
<li ng-repeat="task in cards">
<div ng-hide="task.list == list._id">
{{task.name}}
</div>
<i ng-click="removeTask(task)" class="fa fa-trash-o"></i></li>
</ul>
<form ng-submit="addTask(list._id, $index, newTask)">
<input type="text" ng-model="newTask" placeholder="add a new task" required />
</form>
</div>
</div>
</div>
But it does not work and so it probably can not be if I want to still create a database for the card field
Position (Later to enable drag & dropping)
Can anyone tell me how to properly display cards in lists?
EDIT;;;
thank you very much for the help.
Can you explain more to me because I still have a problem with the cards
I did directiv in angularJS:
App.directive('myList', function() {
return {
restrict: 'E',
replace: true,
template: '<div style="float: left; margin-left: 5px;"><div id="tasks">{{list.name}}<br>{{card.name}}</div></div>'
};
});
App.directive('myCard', function() {
return {
restrict: 'E',
replace: true,
template: '<div style="float: left; margin-left: 5px;"><div id="tasks">{{card.name}}</div></div>'
};
});
and in index.ejs
<my-list ng-repeat="list in lists" list-data="list"></my-list>
<my-card ng-repeat="card in listData.cards" card-data="card"></my-card>
I also did AJAX inquiry after all cards :
https://gist.github.com/anonymous/ed17c3fd675ea4361cb8fbd78e94cb37
name: its name card
list: its _id list
In $scope.cards I stores AJAX inquiry after all cards,
Its my card model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CardSchema = new Schema({
name: { type: String, maxlength: 20, required: true },
// description: { type: String, maxlength: 300 },
list: { type: Schema.Types.ObjectId, ref: 'List' },
updated: { type: Date, default: Date.now },
created: { type: Date, default: Date.now },
active: Boolean
});
module.exports = mongoose.model('Card', CardSchema);
And I have no idea how this loop looks, would you help me somehow?

It's not that easy to solve with two ng-repeat's. You may want to create your list and card directives because eventually they will be complex views:
<my-list ng-repeat="list in lists" list-data="list"></my-list>
And in my-list directive, you can create a loop to to render cards:
<my-card ng-repeat="card in listData.cards" card-data="card"></my-card>

Related

create observables dynamically and show it in html ,knockout?

HTML :-
<div class="row" style="margin-left: 10px;" data-bind="foreach: {data: data, as: 'data1'}">
<span style="color: red; display: none;" data-bind="attr:{'id':data1.mandatory!=0?'id'+data1.dynamicid:''},text: 'You have selected ' +app.vm.observables.totalSelected()+ ' Observation areas. Please restrict to only 2.'"></span>
</div>
here the observable is same for every div element id so value is showing same how to do it dynamically?
JAVASCRIPT :-
`$('#id'+dynamicid+' input:checkbox.paramValues:checked').each(function(e){
DataImprove++;
});`
if(DataImprove>2){
vm.observables.totalSelected(DataImprove);
}
Need to create observables dynamically based on the div element ids and show it in the frontend HTML.
I'm not entirely sure I understand what you are trying to do, but hopefully this helps
I think it would make sense to move some of the functionality out out the view and into a viewModel
var externalData = [{
mandatory: false,
dynamicid: 1,
}, {
mandatory: false,
dynamicid: 2,
}, {
mandatory: 1,
dynamicid: 3,
}, {
mandatory: false,
dynamicid: 4,
}];
function ViewModel() {
var self = this;
self.data = ko.observableArray([]);
self.totalSelected = ko.pureComputed(function() {
return self.data().filter(function(i) {
return i.selected() === true;
}).length;
});
self.selectedText = ko.pureComputed(function(){
return 'You have selected ' + self.totalSelected() + ' Observation areas.';
});
var mappedData = externalData.map(function(item) {
return {
mandatory: item.mandatory,
dynamicid: item.dynamicid,
selected: ko.observable(false),
mandatoryStatus: item.mandatory == true ? 'mandatory' : ''
};
});
self.data(mappedData);
}
var vm = new ViewModel();
ko.applyBindings(vm);
.mandatory {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<span data-bind="text: selectedText"></span>
<ul data-bind="foreach: {data: data, as: 'data1'}">
<li data-bind="class: mandatoryStatus">
<label data-bind="text: dynamicid"></label>
<input type="checkbox" data-bind="checked: selected" />
</li>
</ul>

Meteor app not inserting elements into collection

I am learning Meteor JS and followed a tutorial to build a menu builder shopping list. I am trying to add some features to it. I added one feature successfully, but now I am trying to create an organization feature where users can join an organization and see all shopping lists related to that organization. The first step is to allow for adding an organization by users.
The form appears, and I was able to insert in to the database from the console, but when I use autoform the objects are not being inserted into the database.
I recently upgraded from Meteor 1.3 to 1.4. I don't believe that is an issue since all of the other forms on the app are inserting properly still.
I have a feeling it has something to do with subscribe/publish, but I am not sure what I am doing wrong.
HTML- neworganization.html
<template name='NewOrganization'>
<div class='new-organization-container'>
<i class='fa fa-close'></i>
{{#autoForm collection='Organizations' id='insertOrganizationForm' type='insert'}}
<div class='form-group'>
{{> afQuickField name='organization'}}
</div>
<div class='form-group'>
{{> afQuickField name='members'}}
</div>
<button type="submit" class="btn btn-primary">Add</button>
{{/autoForm}}
</div>
</template>
organizations.html
<template name='Organizations'>
<h3>Your Organizations</h3>
{{#if $.Session.get 'newOrganization'}}
{{> NewOrganization }}
{{else}}
<button class='btn btn-organization btn-primary'>Add an Organization</button>
<button class='btn btn-join'>Join an Organization</button>
<button class='btn btn-deny'>Leave an Organization</button>
{{/if}}
<section class='organization-list'>
{{#if Template.subscriptionsReady}}
{{#each organizationList}}
{{> OrganizationItem}}
{{/each}}
{{else}}
<p>Loading...</p>
{{/if}}
JS- organizations.js
Template.Organizations.onCreated(function() {
this.autorun(() => {
this.subscribe('organizations');
});
});
Template.Organizations.helpers({
organizations() {
return Organizations.find({});
}
});
Template.Organizations.events({
'click .btn-organization': () => {
Session.set('newOrganization', true);
}
});
Template.NewOrganization.helpers({
organizationList: () => {
var organizationItems = Organizations.find({});
return organizationItems;
}
});
newOrganization.js
if (Meteor.isClient) {
Meteor.subscribe('organizations');
}
Template.NewOrganization.events ({
'click .fa-close': function () {
Session.set('newOrganization', false);
}
});
collections/organizations.js
import SimpleSchema from 'simpl-schema';
SimpleSchema.extendOptions(['autoform']);
Organizations = new Mongo.Collection('organizations');
Organizations.allow({
insert: function(userId){
return !!userId;
},
update: function(userId, doc){
return !!userId;
}
});
OrganizationSchema = new SimpleSchema ({
organization: {
label: "Organization Name",
type: String
},
id: {
label: "ID",
type: String,
autoform: {
type: "hidden"
}
},
members: {
type: Array
},
"members.$": Object,
"members.$.name": String,
"members.$.role": String,
inOrganization: {
type: Boolean,
defaultValue: true,
autoform: {
type: 'hidden'
}
},
createdAt: {
type: Date,
label: "CreatedAt",
autoform: {
type: "hidden"
},
autoValue: function() {
return new Date();
}
}
});
Meteor.methods({
deleteOrganizations: function(id) {
Organizations.remove(id);
}
});
Organizations.attachSchema(OrganizationSchema);
The problem is in the way the Schema was designed. I had inserted an id into the schema. My reasoning was that I wanted to have a way to add and remove members from an organization. What I did not take into account was that Mongo autogenerates an id for database object and by designing my schema in this way, I was creating a conflict. I removed the id from my schema and removed the problem.
Here is the new collections/organizations.js file:
import SimpleSchema from 'simpl-schema';
SimpleSchema.extendOptions(['autoform']);
Organizations = new Mongo.Collection('organizations');
Organizations.allow({
insert: function(userId){
return !!userId;
},
update: function(userId, doc){
return !!userId;
}
});
OrganizationSchema = new SimpleSchema ({
organization: {
label: "Organization Name",
type: String
},
members: {
type: Array
},
"members.$": Object,
"members.$.name": String,
"members.$.role": String,
inOrganization: {
type: Boolean,
defaultValue: true,
autoform: {
type: 'hidden'
}
},
createdAt: {
type: Date,
label: "CreatedAt",
autoform: {
type: "hidden"
},
autoValue: function() {
return new Date();
}
}
});
Meteor.methods({
deleteOrganizations: function(id) {
Organizations.remove(id);
}
});
SimpleSchema.debug = true;
Organizations.attachSchema(OrganizationSchema);

how do i store ng-repeat array form data in meanjs?

I am using MEANJS from meanjs.org.
trying to store ng-repeat array data for deal which has dealtype and dealprice as array under it, but unable to do so.
i have setup addFields for the ng-repeat input tag in the create form, but it does not store the data. here is my code.
food.server.model.js
var FoodSchema = new Schema({
created: {
type: Date,
default: Date.now
},
name: {
type: String,
default: '',
required: 'Please fill Food name',
trim: true
},
deal: [{
dealtype: {
type: String,
default: '',
trim: true
},
dealprice: {
type: String,
default: '',
trim: true
}
}],
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
foods.client.controller.js
// initial array setup
var deal = [ { dealtype: '',dealprice: '' }, {dealtype: '',dealprice: '' } ];
$scope.food = {};
$scope.food.deal = deal;
$scope.addItem = function() {
$scope.food.deal.push({
dealtype: '',
dealprice: ''
});
};
// Create new Food
$scope.create = function (isValid) {
$scope.error = null;
if (!isValid) {
$scope.$broadcast('show-errors-check-validity', 'foodForm');
return false;
}
// Create new Food object
var food = new Foods({
name: this.name,
deal:[{
dealtype: this.dealtype,
dealprice: this.dealprice,
}],
});
// Redirect after save
food.$save(function (response) {
$location.path('foods/' + response._id);
// Clear form fields
$scope.name = '';
$scope.dealtype = '';
$scope.dealprice = '';
}, function (errorResponse) {
$scope.error = errorResponse.data.message;
});
};
create-food.client.view.html
<form name="foodForm" class="form-horizontal" ng-submit="create(foodForm.$valid)" novalidate>
<fieldset>
<div class="col-md-12">
<md-input-container flex="">
<label >Food Name</label>
<input type="text" data-ng-model="name" id="name" required>
</md-input-container>
</div>
<div ng-repeat="de in food.deal">
<div class="col-md-6">
<md-input-container class="">
<label class="" for="dealtype">Dealtype</label>
<input type="text" data-ng-model="de.dealtype" id="dealtype" >
</md-input-container>
</div>
<div class="col-md-6">
<md-input-container class="">
<label class="" for="dealprice">Dealprice</label>
<input type="text" data-ng-model="de.dealprice" id="dealprice" >
</md-input-container>
</div>
</div>
<a href ng:click="addItem()" class="btn btn-small">add item</a>
<button class="md-primary md-raised width-100 md-whiteframe-5dp" type="submit">Create Food</button>
<div ng-show="error" class="text-danger">
<strong ng-bind="error"></strong>
</div>
</fieldset>
</form>
Try to set your schema up without the embedded array and send without deal. If that works you may need to set up your schema with a subdocument.
If you are wanting to set your deal property up as a Subdocument you would need to follow this. You would define a schema for deal separately. Something like this:
var dealSchema = new Schema({ {
dealtype: {
type: String,
default: '',
trim: true
},
dealprice: {
type: String,
default: '',
trim: true
}
} });
var FoodSchema = new Schema({
...,
deal: [dealSchema]
})

Error copying req.body properties into Mongoose Model

First of all I have to say that I'm new in Angular and node technologies. So sorry for my ignorance.
I get this error when I try to save an Entity from edition view: 'Cast to ObjectId failed for value "[object Object]" at path "category"'.
Well, I've got these code:
HTML:
<form class="form-horizontal" data-ng-submit="update()" novalidate>
<fieldset>
<div class="form-group">
<label for="listaCat">Categoría:</label>
<select id="listaCat" class="form-control" data-ng-Fmodel="notification.category" data-ng-options="c.name for c in listaCategorias track by c._id">
</select>
</div>
<div class="form-group">
<label class="control-label" for="name">Descripción</label>
<div class="controls">
<input type="text" data-ng-model="notification.name" id="name" class="form-control" placeholder="Descripción" required>
</div>
</div>
<div class="form-group">
<input type="submit" value="Guardar" class="btn btn-default">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>`
Angular controller:
$scope.update = function() {
var notification = $scope.notification;
notification.$update(function() {
$location.path('notifications/' + notification._id);
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
Server side controller:
var mongoose = require('mongoose'),
errorHandler = require('./errors.server.controller'),
Notification = mongoose.model('Notification'),
_ = require('lodash');
exports.update = function(req, res) {
var notification = req.notification;
notification = _.extend(notification , req.body);
notification.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(notification);
}
});
};
Mongoose Model:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var NotificationSchema = new Schema({
name: {
type: String,
default: '',
required: 'Rellena la notificación',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
category: {
type: Schema.ObjectId,
ref: 'Category'
}
});
mongoose.model('Notification', NotificationSchema);
var CategorySchema = new Schema({
name: {
type: String,
default: '',
required: 'Rellena la categoría',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Category', CategorySchema);
So, if I debug inside Server controller at update method with WebStorm, I can see that req.body comes with each attribute well formed, but after convert req.body into Notification Mongoose Model with:
notification = _.extend(notification , req.body);
the category attribute is not a Model but an ObjectId. It seems as lodash.extend is not working properly for complex attributes. I've tried many other ways of cloning the object but without success.
Finally I solved it, with this line inside the angular controller:
notification.category = $scope.notification.category._id;
notification.$update(function() {
Anyway, I think that this is not the right way. I guess there must be a way of copying the req.body properties into a mongoose model without doing it manually for the complex properties.
Thanks a lot in advance!
Since you are working on AngularJS and ExpressJS, i would suggest you to use $resource service which is exactly meant for interacting with the rest API.
**$resource** contains these default set of actions:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
There is nice documentation available in the link that i shared above.
In your case:
i assume, http://localhost:300/notifications/:id, this might be your rest url where you want to perform update action.
You can create your custom services like:
var module = angular.module('myapp.services',['ngResource']);
module.factory('MyAppUpdateService',function($resource){
return $resource('notifications/:id',
{
id: '#id'
},
{
'update': { method:'PUT' }
}
);
});
Now inside your angular app controller you can inject this service as dependency and hence it will be available to perform update in that REST url.
angular.module('myapp',['ngResource','myapp.services']);
angular.module('myapp').controller('MeetupsController',['$scope','$resource','$state','$location','MeetupUpdateService','socket',
function($scope,$resource,$state,$location, MyAppUpdateService){
$scope.updateMeetup = function(){
$scope.updateService = new MyAppUpdateService();
$scope.updateService.name = $scope.notification.name;
.
.
.
$scope.updateService.$update({id:$scope.notification.category._id},function(result){
$location.path("/meetup/")
});
}
})]);
So this was just an example, if you want more comprehensive implementation. Look here, i am creating a MEAN seed of my own, and i am doing the same.
Any doubt please do ask.

extend mean module findOne() to handle other attributes that strings

When start a new meanjs project (mongoose, angular etc.) using the generator and add a CRUD-module i get methods like this:
$scope.findOne = function() {
$scope.income = Incomes.get({
incomeId: $stateParams.incomeId
});
In my income server model is shown below, it has some different attributes and some different object types on these attributes, for example, number, date and string.
When i get data in my $scope.income after the promise "$scope.findOne" has succeded all my data are strings. Do i need to cast each and every one of them to their proper type?
In my front end i want to present the different types in the input elements of my "update" view. For example:
<label class="control-label" for="date">Date of transaction</label>
<div class="list-group-item">
<div class="controls">
<input type="date" data-ng-model="income.date" id="date" class="form-control" placeholder="Date" required>
</div>
This does not work since the object $scope.income.date consists of a string. Changing the input type to string makes it show up. But I want to use a date picker here.
Should I write something like:
$scope.findOne = function() {
Incomes.get({
incomeId: $stateParams.incomeId
}).then(function(data){
var dateVar=new Date(data.date);
var amountVar =Number(data.amount)
$scope.income ={date: dateVar, name: data.name, amount:amountVar}()
);
What is best practise here?
Model I am using:
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Income Schema
*/
var IncomeSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Income name',
trim: true
},
amount: {
type: String,
default: '',
required: 'Please fill Income amount',
trim: true
},
date: {
type: Date,
default: '',
required: 'Please fill Income date',
trim: true
},
monthly: {
type: Boolean,
default: '',
required: 'Please fill whether income is recurring monthly',
trim: true
},
yearly: {
type: Boolean,
default: '',
required: 'Please fill whether income is recurring yearly',
trim: true
},
account: {
type: Schema.ObjectId,
ref: 'Account',
required: 'Please select account'
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Income', IncomeSchema);
First I had to get a hold of the promise, than I easily could build more complex objects from the Incomes.get response. The data is sent over the network as JSON and there fore it is just text, so I needed to instantiate it to the proper types using f ex. Date and Number:
Incomes.get({
incomeId: $stateParams.incomeId
}).$promise.then(function(data){
var dateVar=new Date(data.date);
var amountVar =Number(data.amount)
$scope.income ={date: dateVar, name: data.name, amount:amountVar}()
);
To make the resources function for remove work properly "this" needed to be used, dont forget that the promise is in another namespace so "that=this" is needed.
var that=this;
Incomes.get({
incomeId: $stateParams.incomeId
}).$promise.then(function(income){
income.date= new Date(income.date);
var recurringVar;
if(income.monthly===true){
recurringVar = 'monthly';
} else if( income.yearly===true){
recurringVar = 'yearly';
}
income.recurring=recurringVar;
that.income=income;
});

Categories

Resources