Can't load dictionary using knockout mapping plugin - dictionary

I found the solution how to use the observable array as dictionary on http://jsfiddle.net/karlhorky/D4D3f/
ko.observableArray.fn.indexBy = function (keyName) {
var index = ko.computed(function () {
var list = this() || [];
var keys = {};
ko.utils.arrayForEach(list, function (v) {
if (keyName) {
keys[v[keyName]] = v;
} else {
keys[v] = v;
}
});
return keys;
}, this);
this.findByKey = function(key) {
return index()[key];
};
return this;
};
I'd like to load data to dictionary using mapping plugin
this.Load = function () {
//this.items.
var mapping = {
'copy': ["Qid"]
};
ko.mapping.fromJS(data, mapping, this.items);
count = 0;
};
but can't search by key data loaded using mapping plugin
demo: http://jsfiddle.net/RqSDv/

The mapping plugin turns regular properties into observable properties.
So in your indexBy you need to handle the case when your keyName refers to a ko.observable.
When you get the key property value with v[keyName] you need to use ko.utils.unwrapObservable (or ko.unwrap if you using a newer version of KO) to make sure to correctly unwrap your observable property:
ko.observableArray.fn.indexBy = function (keyName) {
var index = ko.computed(function () {
var list = this() || [];
var keys = {};
ko.utils.arrayForEach(list, function (v) {
if (keyName) {
keys[ko.utils.unwrapObservable(v[keyName])] = v;
} else {
keys[v] = v;
}
});
return keys;
}, this);
this.findByKey = function (key) {
return index()[key];
};
return this;
};
Demo JSFiddle.

Related

asp.net "put" method with angular js

im workin with my website and actually workin with 3 methods-put,post,delete. In my code i did two of them:delete and post and they are correct, but i have no idea how i can do put do edit my TODO list.
That's my code, if you can help me i'll be glad.
Have a nice day.
This is a service .js file
app.factory('reservationService', ReservationService);
function ReservationService($http) {
var CreateReservation = function (reservation) {
return $http.post("api/todo", reservation);
}
var EditReservation = function (id) {
return $http.put("api/todo/", + id);
}
var DeleteReservation = function (id) {
return $http.delete("api/todo/" + id);
}
var GetAll = function () {
return $http.get("api/todo");
}
return {
CreateReservation: CreateReservation,
EditReservation: EditReservation,
DeleteReservation: DeleteReservation,
GetAll: GetAll
}
}
this is a angular maincontroller code
app.controller('mainCtrl', mainCtrl);
function mainCtrl($scope, reservationService) {
$scope.list = [];
$scope.reservation = {};
getReservations();
InitDateTimePickers();
$scope.isSelected = function () {
return getSelectedItems().length > 0;
};
$scope.append = function (id) {
var editedItem = _.first(getSelectedItems());
$scope.reservation = editedItem;
reservationService.EditReservation(id).then(function (result) {
getReservations();
});
};
function getReservations() {
reservationService.GetAll().then(function (result) {
for (var i = 0; i < result.data.length; i++) {
result.data[i].timeFormatted = moment(result.data[i].Time, "HH:mm").format("hh:mm");
}
$scope.list = result.data;
});
}
function removeReservation(id) {
reservationService.DeleteReservation(id).then(function (result) {
getReservations();
});
}
$scope.add = function () {
reservationService.CreateReservation($scope.reservation).then(function (result) {
getReservations();
});
};
function InitDateTimePickers() {
$('#timepickerFrom').bootstrapMaterialDatePicker({ date: false, format: 'HH:mm' }).on('change', function (e, date) {
}); }
$scope.remain = function () {
var count = 0;
angular.forEach($scope.list, function (todo) {
count += todo.done ? 0 : 1;
});
return count;
};
var getSelectedItems = function () {
return _.filter($scope.list, function (n) {
return n.done;
});
}
$scope.archive = function () {
var itemsToRemove = getSelectedItems();
_.each(itemsToRemove, function (item) {
removeReservation(item.id)
});
};
$scope.edit = function () {
var editedItem = _.first(getSelectedItems());
$scope.reservation = editedItem;
}
};
You can pass entire entity to the server to update it:
var EditReservation = function (reservation) {
return $http.put("api/todo/" + reservation.id, reservation);
}
Also it seems that this string contains typo: return $http.put("api/todo/", + id);

Create a universal helper variable

Is there a way to create a variable at the top of template helpers to remove duplication.
In this particular situation I'm using var candidate = FlowRouter.getParam('id'); and I have to create the variable in each helper. I assume there is a better way.
professionalOverview: function() {
var candidate = FlowRouter.getParam('id');
return ProfessionalOverview.findOne({ candidateUserId: candidate });
},
candidateImg: function() {
var candidateUserId = FlowRouter.getParam('id');
return Files.findOne({ userId: candidateUserId });
},
EDIT
Template.talentProfileNew.onCreated(function() {
var self = this;
self.autorun(function(){
this.candidateUserId = new ReactiveVar(FlowRouter.getParam('id'));
}
});
Template.talentProfileNew.helpers({
candidate: function() {
console.log(Template.instance().candidateUserId.get());
return Meteor.users.findOne({_id: Template.instance().candidateUserId.get()});
}
});
you could read it once in onCreated() and put it in a reactive var. e.g.
Template.Foo.onCreated(function() {
this.candidateUserId = new ReactiveVar(FlowRouter.getParam('id'));
});
Template.Foo.helpers({
candidateImg() {
return ProfessionalOverview.findOne({ userId: Template.instance().candidateUserId.get()});
}
});

Sharing data stored in angularjs

I'm trying to shared data between controller.
I'm calling data, then stored in AngularJS Factory variable.
My goal when stored the data was to make it accessible to any controller. But in application, every time i called the stored data from each controller, seems like i got a new instance of my factory instead of my factory that already contain the data.
Do you think i'm doing the wrong way when using factory or there was something i've been missed ?
Here it is
Factory Code:
var Credentials = ['abc'];
function load() {
var service = HeaderService.get("api/CredentialsAPI/get");
service.then(function (response) {
if (response.status == 200)
Credentials = response.data;
});
alert("inside:" + Credentials.length);
}
load();
return {
SubmitCredentials : function (obj) {
angular.forEach(obj, function (value) {
Credentials.push(value);
});
},
GetCredentials : function (name) {
var datax = {};
alert(Credentials.length)
angular.forEach(Credentials, function (value) {
if (value.Name == name) {
datax = value;
}
});
return datax;
}
}
Home Controller:
loadHome();
function loadHome() {
$scope.Credentials = CredentialsService.GetCredentials("Task");
}
AssignTask
$scope.showSubmitView = false;
//----------------------------------function--------------------------------------
$scope.Credentials[] = CredentialsService.GetCredentials("Task");
You're referencing a new array every time. That's why you're getting new data. You should be referencing the service instead, and have the service take care of the push() and get for you.
Factories and Services are singletons... Meaning they're only instantiated once. The pattern to share data is below:
Factory
app.factory('CredentialService',["$http", function($http) {
var credentials = [];
var submitCredentials = function(obj) {
angular.forEach(obj, function(value) {
credentials.push(value);
});
}
var getCredentials = function(name) {
var datax = {};
if(credentials.length === 0)
return datax;
angular.forEach(credentials, function(value) {
if(value.Name === name) {
datax = value;
break; //i think you meant to break; over here
}
});
return datax;
}
//return the service;
return {
getCredentials: getCredentials,
submitCredentials: submitCredentials
};
}]);
Controller
app.controller("Ctrl1", ["$scope", "CredentialService", function($scope, CredentialService) {
var credObj = CredentialService.getCredentials('blahblahblah');
var someNewCredObj = 'blahhhh';
CredentialService.submitCredentials(someNewCredObj);
}]);

Firebase return multiple objects

I am using firebase and in below query extand() is a function that concatenate the objects. Can some one help me to remove $timeout from my query ?
currently i am waiting for my playerList to fill.
var getJoinedPlayers = function(gameId){
var deferred = $q.defer();
var playerList = {};
var usersRef = new Firebase(FBURL+'users');
var gameRef = new Firebase(self.firebaseURL);
var gamePlayersRef = gameRef.child(gameId).child("players");
gamePlayersRef.on("child_added", function(snap) {
usersRef.child(snap.key()).once("value", function(data) {
playerList[snap.key()] = extend({'playerId': snap.key()},data.val());
})
});
$timeout(function() {
if (playerList) {
deferred.resolve(playerList);
} else {
reason = {'message': "player Not found"};
deferred.reject(reason);
}
}, 1300);
return deferred.promise;
};
I would simplify this by replacing "child_added" with "value". This will return the list of players, which you could iterate over with regular JS.
Then call
usersRef.child(snap.key()).once("value", function(data)
for each of of the items in the result, and push each of these promises into an array
promiseArray.push(usersRef.child(snap.key()).once("value", function(data)...
then you could
$q.all(promiseArray).then(...
that will combine all promises into a single promise

Setting $scope.items in Angular Binding

I have a service with the following function,
public object Get(AllUsers request)
{
var users = XYZ.GetAllUsers();
var userList = users.Cast<XYZ>();
return new AllUsers
{
UsersAcc = userList.Select(ConvertToEntity).ToList()
};
}
I am trying to get the results from angular controller.
function UserAccountController($scope, $location, $filter, UserAccount) {
#scope.items = function(){
var abc = UserAccount.query();
return abc.UsersAcc
}
}
Here is my Service
angular.module('userAccService', ['ngResource']).factory('UserAcc', function($resource) {
return $resource('/api/useracc/:id', {}, {
query: {
method: 'GET',
}
});
I am new to angular service, and can't seem to make it to work.
You need to create an array object and return it. After the query is done you can populate that same instance with the list UsersAcc. Keep in mind that $scope.items will be [] untill the query returns with data.
$scope.items = getUsersAcc();
function getUsersAcc() {
var dataArray = new Array();
UserAccount.query(function (data) {
var list = data.UsersAcc;
for (var i = 0, c = list.length; i < c; i++) {
dataArray.push(list[i]);
}
};
return dataArray;
};

Resources