I have an angular.js single page app, with initial data gathered from a rest endpoint.
This app gets a list of IDs representing a saved models, as well as a tree of options to populate some cascading dropdowns.
How can I set the default path in the tree based on my IDs from the model?
Some illustrative code:
Models:
DefaultOptions = [
{"Id" : 044},
{"Id" : 142},
{"Id" : 244}
];
OptionsTree = [
{"Text" : "Option1",
"subOptions" : [
{"Text" : "SubOption1", "Id" : 044},
{"Text" : "SubOption2", "Id" : 142}
]},
{"Text" : "Option2",
"subOptions" : [
{"Text" : "SubOptionA", "Id" : 3033},
{"Text" : "SubOptionB", "Id" : 244}
]}
];
HTML:
<div ng-repeat="member in DefaultOptions">
<select ng-model="option"
ng-options="o as o.Text for o in OptionsTree">
</select>
<select ng-model="subOption"
ng-options="s as s.Text for s in option.subOptions"
ng-disabled="!option"
ng-change="member.Id = subOption.Id">
</select>
</div>
This HTML will properly update the DefaultOptions ID if the user selects a new one, but cannot set the default. What am I missing?
Change your selects' ng-model to account for the ng-repeat:
Then put this in your controller:
// Main dropdown
$scope.member.option = OptionsTree[0];
and then:
// Sub dropdown
$scope.member.subOption = OptionsTree[0].subOptions[0].id
Since your question didn't state if you wanted the id or the whole object I assumed the whole object for the main dropdown and just the id for the sub dropdown.
Related
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.
I have list that gets filled up with 'allergies' that it fetches from a web service. So allergies could look something like this:
$scope.formData.allergies = [
{
'id' : 1,
'description' : 'Potassium Cyanide'
},
{
'id' : 2,
'description' : 'Blue ring octopus'
},
{
'id' : 3,
'description' : 'Poison dart frog'
},
];
Which then gets used to populate a list of checkbox inputs:
<li class="item item-checkbox" ng-repeat="allergy in formData.allergies">
<label class="checkbox">
<input type="checkbox" name="selectedAllergies" value="allergy.id">
</label>
{{allergy.description | uppercase}}
</li>
But I'm struggling on how to find out what the user actually selected? Doing this after the user selected a few:
console.log($scope.selectedAllergies);
just returns undefined...
Your checkbox input has a value (what it will set the model to) but no ng-model, so it doesn't know what to do with this value.
I think the easiest would be to modify the allergies array, so you could have the following code :
<li class="item item-checkbox" ng-repeat="allergy in formData.allergies">
<label class="checkbox">
<input type="checkbox" name="selectedAllergies" ng-model="allergy.selected">
</label>
{{allergy.description | uppercase}}
</li>
Without any value the allergy.selected should be set to a truthey or falsey value depending on the checkbox state.
You need to add an ng-model to the <input> element to do the binding
<input ng-model="allergy.checked" type="checkbox">
And then initialise it in the controller like this
$scope.formData.allergies = [
{
'id' : 1,
'description' : 'Potassium Cyanide',
'checked' : false
},
{
'id' : 2,
'description' : 'Blue ring octopus',
'checked' : false
},
{
'id' : 3,
'description' : 'Poison dart frog',
'checked' : false
},
];
Initially all of them will be in un-checked state and when the user selects a check box, say the first one, the value of $scope.formData.allergies[0].checked will be true
i created a "todolist" with angular-meteor (meteor add urigo:angular).
This are the files which are involved:
config.js (ui-router file)
.state('app.todolist', {
url: '/todolist',
title: 'Todolist',
controller: 'TodoListController',
controllerAs: 'tc',
templateUrl: helper.basepath('todolist.ng.html'),
authenticate: true
})
todolist.ng.html (static file)
<h3>Todo - List
<small>Example app of a todo list.</small>
</h3>
<ul ng-repeat="task in tc.tasks">
<li>{{task.text}}</li>
</ul>
todolist.js (Controller)
angular.module('angle').controller('TodoListController',
['$scope', '$meteor',
function($scope, $meteor){
var vm = this;
vm.tasks = $meteor.collection(Tasks);
}]
);
the "tasks" collection is loaded in the "lib" folder and has documents inserted
meteor:PRIMARY> db.tasks.find()
{ "_id" : ObjectId("55bf7d98251a0c51417732bf"), "text" : "zweiter eintrag", "createdAt" : ISODate("2015-08-03T14:41:28.534Z") }
{ "_id" : ObjectId("55bf7dab251a0c51417732c0"), "text" : "zweiter eintrag", "createdAt" : ISODate("2015-08-03T14:41:47.045Z") }
{ "_id" : ObjectId("55bf7dac251a0c51417732c1"), "text" : "zweiter eintrag", "createdAt" : ISODate("2015-08-03T14:41:48.685Z") }
{ "_id" : ObjectId("55bf7dad251a0c51417732c2"), "text" : "zweiter eintrag", "createdAt" : ISODate("2015-08-03T14:41:49.003Z") }
{ "_id" : ObjectId("55bf7dad251a0c51417732c3"), "text" : "zweiter eintrag", "createdAt" : ISODate("2015-08-03T14:41:49.261Z") }
lib/js/databases.js
Tasks = new Mongo.Collection('tasks');
But when I run my app and click on the "Todolist" I can't see anything. It doesnt list any task.text... If I use a static array instead of mongodb everything works fine. (for example: vm.tasks = [{ text: "Task1" },{ text: "task2" }]; ).
But with mongodb noting is showing. I checked the database connection, this works. I dont get any errors, when loading the app and accessing the "Todolist".
Any ideas?
Regards,
Simon
Ok problem is solved.
I created the databases.js in the "myapp/client/lib" folder instead of the pure "myapp/lib" folder.
bad mistake... but its solved :) Thanks for help!
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" }
}
);
{
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