how to update nested json array using meteor.js - javascript

I am want to insert these values into mongodb and here is my code, i am able to insert it but when i was updating only access_policy inside admin_section, i was not able to do that, can anyone please help me, how can i solve it :
meteor.json
{
"_id" : ObjectId("555ebffa7c88507a4a683e81"),
"section_id" : "Admin Section",
"is_active" : true,
"admin_section" : [
{
"_id" : 1,
"info" : "Setup custom access policy for user groups",
"sub_section" : "Setup - access policy",
"access_policy" : "ROOT"
},
{
"_id" : 2,
"info" : "Customize access policy for main sections",
"sub_section" : "Manage - access policy",
"access_policy" : "ROOT"
},
{
"_id" : 3,
"info" : "Manage user groups for DX-Client application",
"sub_section" : "Manage - user groups",
"access_policy" : "ROOT"
},
{
"_id" : 4,
"info" : "Manage users for DX-Client application",
"sub_section" : "Create - user",
"access_policy" : "ADMINISTRATOR"
},
],
"access_policy" : "ADMINISTRATOR"
}
meteor.html
<table class="table table-bordered">
<tbody>
{{#each temp_admin_section}}
{{#if admin_section}}
<tr class="bgLight">
<td class="left" id="one"><b>{{ section_id }}</b></td>
<td class="left" id="two"><b>RESTRICTED</b> - <code contenteditable="true" class="edited"><input value="{{ access_policy }}" /></code><a class="add-access pull-right">add</a></td>
</tr>
{{#each admin_section}}
<tr>
<td class="left" id="one">{{ sub_section }}</td>
<td class="left" id="two">RESTRICTED - <code contenteditable="true" class="edited">
<input value="{{ access_policy }}" /></code></td>
</tr>
{{/each}}
{{/if}}
{{/each}}
</tbody>
</table>
meteor.js
'change .edited': function(event, template){
var to = event.target.value;
var list = to.split(",");
map.update(
{"_id": this._id, "admin_section._id" : 1},
{$set: {"admin_section.$.access_policy": list}}
);
}

All client-side code is considered untrusted unless you call a Meteor.call and let a server-side method do the update. If you look in the console, you will probably see an error like this:
{
error: 403,
reason: "Not permitted. Untrusted code may only update documents by ID.",
details: undefined, message: "Not permitted. Untrusted code may only update documents by ID. [403]",
errorType: "Meteor.Error"
}
On the client-side, you can only update 1 document at a time, and you must choose the document to update by ID, so the 1st argument needs to be a mongo document ID, not a mongo selector:
MyCollection.update(
this._id,
{
$set: { "admin_section.1.access_policy": "TEST" }
}
)
Also, to update a sub-document of an array, rather than specifying the ID in the 1st argument as a selector, notice how I am specifying the ID inside the $set statement.
If you want to update all elements in the array, you have to loop through all of them individually:
var doc = MyCollection.findOne(this._id);
var adminSections = doc.admin_section;
for (i = 0; i < adminSections.length; i++) {
// If you need to access a value in the nested doc:
var nestedDoc = adminSections[i];
MyCollection.update(
this._id,
{
$set: { "admin_section." + (i+1) + ".access_policy": "someValue" }
}
);
{

Related

Query for sorting a date that is inside another object in firebase

I'm developing a chat in angularjs where I have a chat list view and a chat view.
What I'm trying to do is sorting my chat list to show the most recent chat on top using Firebase and JS, I did my research but all of the questions I found they have the date directly as a child but inside my DB my date is inside a 'lastMessage' key. My dates are the following format.
date: 1528417493034
Any help would be highly appreciated
My structure is the following:
"Users": {
"nCsXbTl8CcXvoviuL5Tt7kiV6Bn1" : {
"contacts" : {
"VN9AFnn4uXgDfoir8DWHnw54zrJ3" : {
"email" : "test#test.com",
"lastMessage" : {
"date" : 1528417493034,
"senderId" : "VN9AFnn4uXgDfoir8DWHnw54zrJ3",
"status" : "success",
"text" : "Yes?",
"type" : "text",
"uid" : "1528417493034VN9AFnn4uXgDfoir8DWHnw54zrJ3"
},
"name" : "test"
},
"cHuR26YaSgbO7ahSVLg1XG5HYer2" : {
"email" : "aaa#aaa.com",
"lastMessage" : {
"date" : 1528417068249,
"senderId" : "cHuR26YaSgbO7ahSVLg1XG5HYer2",
"status" : "success",
"text" : "Trigeeeers?",
"type" : "text",
"uid" : "1528417068249cHuR26YaSgbO7ahSVLg1XG5HYer2"
},
"name" : "aaa"
}
}
}
My chat list view is the following:
<div layout="row" class="main-chat-container" layout-wrap>
<div class="list-container" flex="30">
<div class="chat-header">
<p>Lista de Chats</p>
</div>
<div class="chats-list">
<div class="chats-header">
<p>Usuarios</p>
</div>
<div class="chats" ng-repeat="chat in chats">
<div class="email-container" ng-click="setUserData(chat)" ng-class="styleData.email == chat.email ? 'new-background' : ''">
<a>{{chat.email}}</a> <p ng-show="counter > 1">{{testData.number}}</p>
</div>
</div>
</div>
</div>
<div class-"chat-container" flex="70">
<ui-view></ui-view>
</div>
And the controller is the following
app.controller('chatController', function (currentAuth, $scope, $firebaseArray, $firebaseObject) {
$scope.chats = [];
$scope.getContactsList = function(){
var listRef = firebase.database().ref('Users').child(currentAuth.uid).child('contacts');
var test = firebase.database().ref('Users').child(currentAuth.uid).child('contacts');
var listArray = $firebaseArray(listRef);
var testArray = $firebaseArray(test);
$scope.chats = listArray;
console.log("TEST ARRAY IS ");
console.log(testArray);
}
$scope.getContactsList();
});
To so a users contacts on the timestamp of their last message, you'd do something like this:
var userRef = firebase.database().ref('Users').child(currentAuth.uid)
var contactsQuery = userRef.child('contacts').orderByChild("lastMessage/date");
Note that this will give you the contacts in chronological order, so you will have to reverse the result in your client.
Alternatively some folks keep an inverted value in a separate property in their database, e.g.
"VN9AFnn4uXgDfoir8DWHnw54zrJ3" : {
"email" : "test#test.com",
"lastMessage" : {
"date" : 1528417493034,
"invertedDate" : -1528417493034,
"senderId" : "VN9AFnn4uXgDfoir8DWHnw54zrJ3",
Since this invertedDate value is inverted, ordering on that property would give you the contacts in reverse chronological order, so that you don't have to reverse them in the client.

AngularJS Expression usage in ng-repeat

I am building a simple webpage where I get some JSON data like this:
{
"Persons" : [{
"Initials" : "jd",
"Name" : "Jhon Doe",
"Email" : "jd#somemail.com",
"Title" : "Some title",
"Phone" : "+999 999 999",
"PictureUrl" : "personimages/jd.jpg"
}, {
"Initials" : "jb",
"Name" : "James Bond",
"Email" : "jb#somemail.com",
"Title" : "Agent",
"Phone" : "+007 007 007",
"PictureUrl" : "personimages/jb.jpg"
}, ...
],
"DistLists" : [{
"ContainedPersons" : ["jd", "jb", ...],
"Title" : "Some Title"
}, {
"ContainedPersons" : ["jd, "hp, ..."],
"Title" : "Some other Title"
}, ...
]
}
And so I am creating a webpage where you can select the different "Groups" in "DistLists".
And by selecting the e.g. "Some Title" group I want to take the "ContainedPersons" array, and loop through "Persons" and display the information for all the "Persons" that are in the "ContainedPersons" array.
My HTML looks something like this:
<!DOCTYPE html>
<html ng-app="WhoIsWho2">
<head>
<script type="text/javascript" src="app/gemApp.js"></script>
</head>
<body ng-controller="WhoIsWho2Controller as wiw2">
<div class="text-center" ng-controller="myCtrl">
<select ng-model="selectedItem" ng-options="item as item.Title for item in distlist"></select>
<p>{{selectedItem.ContainedPersons}}</p>
<table align="center" border="1">
<tr ng-repeat="ini in selectedItem.ContainedPersons">
<td>
<p ng-repeat="employ in wiw2.employees | filter: {Initials:'{{ini}}'}">Hejsa Test 2 {{employ.Name}} </p>
</td>
</tr>
</table>
</div>
</body>
</html>
And my JavaScript file containing angular looks something like this.
(function () {
var app = angular.module('WhoIsWho2', []);
app.controller('WhoIsWho2Controller', function () {
this.employees = persons;
});
app.controller('myCtrl', function($scope) {
$scope.distlist = distlist;
});
})();
Where persons and distlist in the JavaScript file is my data. (Locally now, but should come from the JSON file)
My problem is that I am not allowed to use the {{ini}} in the ng-repeat in my <p> element.
Is there another way to achieve this?
Or maybe with another design?
All help is appreciated.
Try Like This :
<tr ng-repeat="ini in selectedItem.ContainedPersons">
<td>
<p ng-repeat="employ in wiw2.employees | filter: {Initials:ini}">Hejsa Test 2 {{employ.Name}} </p>
</td>
</tr>

Firebase / Angular JS show only firebase entries created by logged in user

Right now I have a table that is currently showing all the entries form an "events" node in firebase.
However, I only want to show the events created by the logged in user. Right now they are showing events created by all users.
I'm guessing I might be able to use an ng-if directive after the ng-repeat in the tag, however, I am not sure what to put into it.
This is my table:
<table class="table table-striped">
<thead>
<tr>
<th>Title</th><th>Location</th> <th>Actions</th>
</tr>
</thead>
<tbody>
<tr scope="row" ng-repeat="event in events | reverse" >
<td>{{event.title}}</td>
<td>{{event.location}}</td>
<td><button class="btn btn-primary" ng-click="events.$remove(event)"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button></td>
</tr>
</tbody>
The user object looks like so:
{
"provider": "password",
"uid": "635gt3t5-56fe-400d-b50b-1a6736f8874a",
"token":
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6Im1pY2hhZWwubGFyaXZpZXJlMTk3M0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlhdCI6MTQ2OTEyNTYyOSwidiI6MCwiZCI6eyJwcm92aWRlciI6InBhc3N3b3JkIiwidWlkIjoiNmY5ZmM0NTUtNTZmZS00MDBkLWI1MGItMWE2NzM2Zjg4NzRhIn19.yIzzV7Or7tUlXi-sSWeioNx6LLoQ0U9qnW1X06rpSmA",
"password": {
"email": "xxxxxx.xxxxxx1234#gmail.com",
"isTemporaryPassword": false,
"profileImageURL": "https://secure.gravatar.com/avatar/5f9effbf8cbea69792c595079cf25d38?d=retro"
},
"auth": {
"provider": "password",
"uid": "635gt3t5-56fe-400d-b50b-1a6736f8874a",
"token": {
"email_verified": false,
"email": "xxxxxx.xxxxxx1234#gmail.com",
"exp": 1469212029,
"iat": 1469125629,
"sub": "635gt3t5-56fe-400d-b50b-1a6736f8874a",
"auth_time": 1469125629,
"firebase": {
"identities": {
"email": [
"xxxxxx.xxxxxx1234#gmail.com"
]
}
}
}
},
"expires": 1469212029
}
My controller looks like this:
angular.module('myApp').controller('ChatCtrl', function($scope, user,
Ref, $firebaseArray, $timeout) {
console.dir('user: ' + JSON.stringify(user));
// synchronize a read-only, synchronized array of events, limit to most recent 10
$scope.events = $firebaseArray(Ref.child('events').limitToLast(10));
// display any errors
$scope.events.$loaded().catch(alert);
// provide a method for adding a event
$scope.addEvent = function(newEvent) {
if (newEvent) {
// push a event to the end of the array
$scope.events.$add({
title: newEvent.title,
location: newEvent.location,
createdBy: user.uid,
createdAt: Firebase.ServerValue.TIMESTAMP
})
// display any errors
.catch(alert);
}
};
function alert(msg) {
$scope.err = msg;
$timeout(function() {
$scope.err = null;
}, 5000);
}
});
This is what the users and events look like in firebase:
To get the results that you're looking for, try using an angularjs filter.
In you controller add a function called
$scope.filterByUID = function(event) {
if (event.createdBy === user.uid) {
return true;
}
return false;
}
This function will act as a filter that only let's through events that were created the current user by comparing the event's createdBy to the user's uid.
Then change this line in your html
<tr scope="row" ng-repeat="event in events | reverse" >
To
<tr scope="row" ng-repeat="event in events | reverse | filter:filterByUID" >
This tells angularjs that you want to have your items filtered with the filter we defined in the controller.
Edit: Here's a reference on using custom filters: AngularJS : Custom filters and ng-repeat

Not able to filter the model using the Ember.Select in Ember.js

The use case is I am trying to filter the model using the Ember.Select, whenever the user clicks the button, the model gets filtered on the basis of the 'Designation' property.
Here's my Ember.Select:
{{view Ember.Select
contentBinding="designations"
optionValuePath="content.id"
optionLabelPath="content.designation"
selectionBinding="roles.selectedDesignation"}}
<button {{action 'filter'}}>Filter</button>
And Here's what I am doing in App.js,
App.TwodController = Ember.Controller.extend({
filteredContent : Ember.computed.oneWay("content"),
selectedDesignation : null,
designations : [{
designation : "Design",
id : 1
}, {
designation : "Writer",
id : 2
}],
actions : {
filter : function() {
var designation = this.get('roles.selectedDesignation');
var filtered = this.get('content').filterProperty('designation', designation);
this.set("filteredContent", filtered);
}
}
});
Here's the full JSBin, http://jsbin.com/iPUxuJU/2/edit
What I might be missing here?
You are missing something in selection binding
{{view Ember.Select
contentBinding="designations"
optionValuePath="content.id"
optionLabelPath="content.designation"
selectionBinding="selectedDesignation"}}
<button {{action 'filter'}}>Filter</button>
In controller logic:
App.TwodController = Ember.Controller.extend({
filteredContent : Ember.computed.oneWay("content"),
selectedDesignation : null,
designations : [{
designation : "Design",
id : 1
}, {
designation : "Writer",
id : 2
}],
actions : {
filter : function() {
var designation = this.get('selectedDesignation.designation');
var filtered = this.get('content').filterProperty('designation', designation);
this.set("filteredContent", filtered);
}
}
});
Here is the working jsbin

Aria Templates - Form Submission Issues

I am trying to submit an aria template form http://ariatemplates.com/,the submission is done to a Spring MVC controller/servlet.
The form is getting submitted all right but i am not able to get the values of the aria elements like date picker,text box etc in the controller.
Request.getParameter is of no use.
Any Help will be appreciated.
Here is my sample tpl file,js file and the Spring Controller.
TPL File
{Template {
$classpath:'view.Turnover',
$hasScript : true
}}
{macro main()}
<form action="test.do" method="POST" id="turnoverform">
<div style="float:left;padding-top: 3em;padding-bottom: 3em;padding-right: 3em;">
{#aria:Div {
sclass : "basic",
width : 740,
height : 300
}}
<p style="font-family:Arial,Helvetica,sans-serif;font-size: medium;">Create Turnover Report</p>
<hr />
{#aria:DatePicker {
label: " begin date:",
labelWidth:190,
width:330,
helptext:"Type date or select",
}/}
{#aria:DatePicker {
margins:"x x x 20",
label: "end date:",
labelWidth:190,
helptext:"Type date or select",
width:330,
}/}
<br/>
<br/>
<br/>
{#aria:TextField {
label : "User id",
labelPos : "left",
helptext : "ID",
width : 250,
block : true,
labelWidth : 80,
bind : {
"value" : {
inside : data,
to : 'value' }
}
}/}
<br />
{/#aria:Div}
<br />
{#aria:IconButton {
icon: "std:confirm",
label:"Create",
width : 300,
tooltip : "Click on this to create a Report",
block: true,
onclick : {
fn : buttonClick
}
} /}
</div>
</form>
{/macro}
{/Template}
Javascript File :
Aria.tplScriptDefinition({
$classpath : "view.TurnoverScript",
$prototype : {
/**
* Callback for the click event on the first button.
* #param {aria.DomEvent} evt Click event
*/
buttonClick : function (evt) {
aria.core.IO.asyncFormSubmit({
formId : "turnoverform",
callback : {
fn : this.onSuccess,
onerror : this.onError,
scope : this
}
});
},
onSuccess : function (evt, args) {
alert("The Template has been created");
//this.$json.setValue(["view:Dialog"], "dialogOpen", true);
},
onError : function (evt, args) {
alert("The Template has not been created due to some Error");
}
}
});
in Aria Templates you don't work normally with DOM elements but with the data model.
The way to achieve what you want is to bind those values to the datamodel using the bind property
{#aria:DatePicker {
label: " begin date:",
labelWidth:190,
width:330,
helptext:"Type date or select",
bind : {
value : {
inside : data,
to : "begin_date"
}
}
}/}
Your datamodel would now contain those values, try to modify those values and see the content of this.data in your template script.
To submit the data you have two options,
Template Script through aria.core.Io.asyncRequest (or maybe the RequestMgr, depending on your application complexity).
This method takes a data string that in case of POST requests is the message body. It has to be a string so you can use aria.utils.json.JsonSerializer.serialize() to convert your datamodel into a string.
aria.utils.json.JsonSerializer.serialize(this.data, config)
In the previous snippet of code config is optional, if provided it should match this bean.
Module controller through submitJsonRequest
The good thing about using a controller is that you separate the logic of connecting to a server from the template and that you can send directly an object as data, serialization is done internally.
The drawback is that you'll probably have to configure your UrlService to convert actions to actual URL. Few more info here

Categories