Convert to KO JS Mapping my code - javascript

I recently started to work with KnockoutJS and i managed to do a simple app to show my data from CouchDB. What i noticed is if i have more data and more nested data i need to appply the mapping plugin in order to get my data more flexible. Some question and answers here are about this plugin but i didn't know how to apply this plugin on my existing web-app.
I recently came a to a problem, i wanted to get the specdial data from my converter and then show it with a computed variable. Even this code does not apply with my view model or i need to apply the plugin : self.Converter = ko.observable(Converter);
So here is my mainJS.
function ViewModel() {
var self = this;
self.myfield = ko.observableArray([]);
self.investigator = ko.observableArray([]);
self.preparatorInfos = ko.observableArray([]);
self.enumInfos = ko.observableArray([]);
//self.Converter = ko.observable(Converter);
//self.Converter = ko.observable(data.Converter);
self.selectDivs = ko.observableArray(['Properties', 'Implements']);
self.selectedDiv = ko.observable();
self.selectDivs2 = ko.observableArray(['Properties', 'Requires']);
self.selectedDiv2 = ko.observable();
}
var db = new PouchDB('http://localhost:5984/helloworld');
var vm = new ViewModel();
db.query("bricksetup/docs").then(function(result) {
var data = result;
console.log(data);
vm.myfield(data.rows);
});
db.query("InvestigatorInfos/docs").then(function(result) {
var data = result;
console.log(data);
vm.investigator(data.rows);
});
db.query("PreparatorInfos/docs").then(function(result) {
var data = result;
console.log(data);
vm.preparatorInfos(data.rows);
});
db.query("EnumInfos/docs").then(function(result) {
var data = result;
console.log(data);
vm.enumInfos(data.rows);
});
ko.applyBindings(vm);
And my View:
<!-- BRICKINFOS -->
<div id="tab1" class="col s12">
<ul class="collapsible" data-collapsible="accordion" data-bind="foreach:myfield">
<li data-bind="with: value">
<div class="collapsible-header">
<i class="material-icons">view_stream</i>
<p class="blue-text" data-bind="text: TypeName"></p>
</div>
<div class="collapsible-body">
<p class="style_p_row" ><b>AssemblyName:</b> <span data-bind="text: AssemblyName"></span></p>
<!-- ko if: Description -->
<p class="style_p_row" ><b>Description:</b> <span data-bind="text: Description"></span></p>
<!-- /ko -->
<p class="style_p_row" ><b>Name: </b><span data-bind="text: Name"></span></p>
<p class="style_p_row" ><b>Obsolete: </b><span data-bind="text: Obsolete"></span></p>
<p class="style_p_row" ><b>TypeName: </b><span data-bind="text: TypeName"></span></p>
<div class="row">
<form class="col s12">
<div class="row">
<div class="col s12 m12">
<div class="col s12 m4 padding_select">
<select class="browser-default "
data-bind="options: $root.selectDivs,
value: $root.selectedDiv,
optionsCaption: 'Choose'">
</select>
</div><!-- end col s6 -->
<div class="col s6 m6" >
<div data-bind="visible: $root.selectedDiv() == 'Properties'" id="Properties">
<!-- ko if: Properties.Properties == ''-->
<p class="blue-text padding_p">Properties</p>is nothing set
<!-- /ko -->
<!-- ko ifnot: Properties.Properties == ''-->
<p class="blue-text padding_p">Properties</p>
<ul data-bind="foreach: Properties.Properties">
<li class="space_bottom">
<b>Name:</b> <span data-bind="text: Name"></span></br>
<b>Converter: </b><span class="converter_class" data-bind="text: converterNames[Converter]"></span></br>
<b>Validation Type: </b><span class="validation_class" data-bind="text:validationName[ValidationType] "></span></br>
<!-- ko if: EnumTypeName -->
<b>EnumType: </b><span class="validation_class" data-bind="text: EnumTypeName"></span></br>
<!-- /ko -->
<!-- ko if: Description -->
<b>Description: </b><span class="validation_class" data-bind="text: Description"></span></br>
<!-- /ko -->
</li>
</ul>
<!-- /ko -->
</div>
<div data-bind="visible: $root.selectedDiv() == 'Implements'" id="Implements">
<p class="blue-text padding_p">Implements Interfaces</p>
<ul data-bind="foreach: Implements.Interfaces">
<li><b>TypeName:</b> <span data-bind="text: $data.TypeName"></span><br></li>
</ul>
</div>
</div>
</div><!-- end col s6 -->
</div>
</div>
</form>
</div><!-- end row -->
</div>
</li>
</ul>
</div>
How my data looks:
I really appreciate the help.

IF you're asking how to use KO mapping, it would be:
instead of
db.query("PreparatorInfos/docs").then(function(result) {
var data = result;
console.log(data);
vm.preparatorInfos(data.rows);
});
it would become:
db.query("PreparatorInfos/docs").then(function(result) {
var data = result;
ko.mapping.fromJS(data, {}, vm.preparatorInfos);
});

Related

after an ng-repeat I need to isolate and grab one elements 'id'

I want to grab the 'id' of the comment I'm hitting reply to and store that to be used for an Ajax call. I can currently grab everything else with ng-model, and it doesn't seem I can use the tactic of value="{{this.id}}" in a hidden input to get the value like I would if I were using jquery.
<script type="text/ng-template" id="comments-temp">
<div>
<ul class="comments" ng-repeat="comment in ctrl.comments">
<li>
<div class="comment" id="{{comment.id}}">
<div class="comment-author">
</div><!-- /.comment-author -->
<div class="comment-content">
<div class="comment-meta">
<div class="comment-meta-author">
Posted by admin
</div><!-- /.comment-meta-author -->
<div class="comment-meta-reply">
Reply
</div>
<div class="comment-meta-date">
<i class="fa fa-calendar"></i><span>{{comment.dateAdded | date: 'medium'}}</span>
</div>
</div><!-- /.comment -->
<div class="comment-body">
<div class="comment-item" id="commentTitle">
<h6>{{comment.title}}</h6>
</div>
{{comment.body}}
</div><!-- /.comment-body -->
</div><!-- /.comment-content -->
</div><!-- /.comment -->
<panel ng-show="showPanel">
<div class="comment-create" ng-model="ctrl.reply">
<form method="post" action="?">
<div class="row">
<div class="col-sm-4">
<div class="form-group ">
<label>Title</label>
<input type="text" class="form-control" ng-model="ctrl.reply.title">
</div><!-- /.form-group -->
</div><!-- /.col-* -->
<div class="col-sm-4">
<div class="form-group hidden">
<label>Title</label>
<input type="text" class="form-control" ng-model="ctrl.reply.name">
</div><!-- /.form-group -->
</div><!-- /.col-* -->
<div class="col-sm-4">
<div class="form-group hidden">
<label>ParentId</label>
<input type="text" class="form-control" value="{{comment.id}}" ng-model="ctrl.reply.parentId">
</div><!-- /.form-group -->
</div><!-- /.col-* -->
</div><!-- /.row -->
<div class="form-group">
<label>Message</label>
<textarea class="form-control" rows="5" ng-model="ctrl.reply.body"></textarea>
</div><!-- /.form-group -->
<div class="form-group-btn">
<button type="button" ng-click="ctrl.replyComment(ctrl.reply); showPanel = false;" class="btn btn-primary pull-right">Post Reply</button>
</div><!-- /.form-group-btn -->
</form>
</div>
</panel>
<div style="height:35px"></div>
</li>
</ul>
</div> <!--comment temp end-->
I hope I've been clear. What I want is this:
<script>
function _replyComment(data){
vm.commentData = data;
vm.commentData.blogId = vm.blogId;
vm.commentData.userId = page.currentUserId;
vm.commentData.typeId = 1;
vm.commentData.parentID = //??????? where I want the value the id of the comment I'm replying too
console.log(vm.commentData);
comments.services.insert(data, _onSuccessComment, _onError);// my ajax is in a separate .js file. it's not important for this demo
}
</script>
After this I of course have to figure out how to nest the replies in the DOM appropriately. But this is a question for a different day. This is where Jquery is easier than angular.
Thanks!
holtc solved it. This might be round about, but I created another click that just stored the comment.id. Then I made a new controller variable and just put it on in my _replyComment function.
vm.getId = _getId;
vm.pId = null;
function _getId(data){
vm.pId = data
console.log(vm.pId)
}
function _replyComment(data){
vm.commentData = data;
vm.commentData.blogId = vm.blogId;
vm.commentData.userId = page.currentUserId;
vm.commentData.typeId = 1;
vm.commentData.parentId = vm.pId;
console.log(vm.commentData);

Change the div content from click in a list?

How can i make this work with AngularJS? Have this list left-side, and need to change the center div content from the click in this list.
I'm using NG-CLICK and NG-REPEAT to get the click and generate the list from a JSON.
angular.module('duall')
.controller('documentationController', [
'$scope',
'$http',
function($scope, $http){
$scope.docs = [];
$http.get('static/titles.json').success(function(doc){
$scope.docs = doc;
}).error(function(error){
console.log(error);
});
$scope.cliked = function(index){
$scope.item = $scope.docs[index]
};
}]);
<div ng-controller="documentationController">
<div class="row">
<div class="col s3" >
<div class="input-field col s12" >
<input id="search" type="search" ng-model="q" aria-label="filter docs"/>
<label for="search"><strong>Pesquise Algo! :)</strong></label>
<i class="material-icons prefix">search</i>
</div>
<ul class="animate-container">
<!-- <li ng-repeat="docs in docs | orderBy:'title' | filter:q as results "> -->
<li ng-repeat="docs in docs | filter:q as results ">
<i class="material-icons tiny">search</i>
<a ng-click="cliked($index)" href="">{{docs.title}}</a>
<div class="divider"></div>
<br>
</li>
<li ng-if="results.length === 0">
<strong>Nada encontrado :(</strong>
</li>
</ul>
</div> <!-- Fim col s3 -->
<div class="col s9">
<div class="container">
CONTENT CLICKED MUST BE HERE!
</div>
</div>
</div><!-- Fim col s9 -->
</div><!-- fim ROW -->
</div><!-- Fim Controller -->
on the ng-click you can call a function that affect a variable that will contain what you want to see in your container. the following code is only a sample to show you the idea :
First in a ng-repeat you can call a function with ng-click directive :
<li ng-repeat="docs in docs | filter:q as results ">
<i class="material-icons tiny">search</i>
<a ng-click="cliked($index)" href="">{{docs.title}}</a>
<div class="divider"></div>
<br>
</li>
Function that will affect a specific variable
$scope.cliked = function(index){
$scope.item = $scope.docs[index]
};
Variable that you can display in the good container :
<div class="container">
{{$scope.item}}
</div>

JSON - knockout.js - nested data

I have the following JSON received at my web application.
I have a knockout viewmodel:
var self = this;
self.ActiveAlarms = ko.observable();
and my JSON call:
$.getJSON("/api/Dashboard/ActiveAlarmsPerAlarmTypeForTurbine/591", function (data) {
objVM.ActiveAlarms(data);
});
And I have my .cshtml page:
<div class="row">
<div class="col-md-12">
<span data-bind="text: objVM.ActiveAlarms.turbine.name"></span>
</div>
</div>
<div class="row" data-bind="foreach: listOfAlarmsPerAlarmType">
<div class="col-md-12">
<span data-bind="text: alarmType.name"></span>
</div>
</div>
But nothing shows up... :-( - what am I missing here?
The rest of the webpage, viewmodel and the knouckout/json works very fine.
Could be a number of things, are you binding the page correctly?
But one thing i noticed what this
<div class="row">
<div class="col-md-12">
<span data-bind="text: objVM.ActiveAlarms().turbine.name"></span>
</div>
</div>
<div class="row" data-bind="foreach: listOfAlarmsPerAlarmType">
<div class="col-md-12">
<span data-bind="text: alarmType.name"></span>
</div>
</div>
You need to add parentheses to the observable object in the markup

accordion toggle collapsing more than targeted divs

In my current piece of code when i try to collapse a letter it collapses the first div of the content when it should collapse all the divs within a letter header - i am not sure how to alter my JavaScript to properly collapse divs within a div.
<div class="accordion-group" data-bind="foreach: Types">
<div class="text_x-large header"> <span data-bind="text:Name()"></span>
</div>
<div class="testing" data-bind="foreach: Users">
<!-- ko if: Letter -->
<div class="text_x-large letterHeader list_accordion_toggle" data-bind="visible: $parent.ShowLetter(), text: Letter"></div>
<!-- /ko -->
<div class="type_list_item smoke_hover" data-bind="template: { name: 'list'}"></div>
</div>
</div>
JavaScript
$(document).on('click', '.list_accordion_toggle', function (event) {
$(this).toggleClass('type_list_item collapse').next().toggle();
});
One approach is to adjust your markup to include a containing DIV element. Like so: jsFiddle
EDIT:
Knockout allows you to set your own markup, so you should be able to modify it like this:
<div class="accordion-group" data-bind="foreach: Types">
<div class="text_x-large header"> <span data-bind="text:Name()"></span>
</div>
<div class="testing" data-bind="foreach: Users">
<!-- ko if: Letter -->
<div class="text_x-large letterHeader list_accordion_toggle" data-bind="visible: $parent.ShowLetter(), text: Letter"></div>
<!-- /ko -->
<div class="wrapper">
<div class="type_list_item smoke_hover" data-bind="template: { name: 'list'}"></div>
</div>
</div>
</div>

<br> become <br> when taken from mongodb meteor

I have a little problem here. my tag became <br> instead when I tried to set the text of label from mongodb.
//my meteor methods
Meteor.methods({
addEventDetails : function(title, details) {
details=details.replace('\n', "<br>");
eventDetails.insert({'title': title, 'details': details});
}
});
//my template function
Template.detailsboard.evt = function(){
return eventDetails.findOne({});
}
//my template
<template name="detailsboard">
<div class="block">
<div class="navbar navbar-inner block-header">
<div class="pull-left"><i class="icon-bookmark"></i><span class="block-header-title">Event Details</span></div>
<div class="pull-right searchbar"></div>
<!-- <div class="pull-right"><span class="badge badge-warning">View More</span></div> -->
</div>
<!-- /block header-->
<!-- block content -->
<div class="block-content-details collapse in">
<ol class="stream-items" id="stream-items-id">
<a class="logo-details" href="/"></a>
<div class="row-fluid" style="padding:10%">
<div class="span12">
<label class="text-inverse details-title">{{evt.title}}</label>
**//problem here**
<p class="text-inverse details-content">this.html({{evt.details}})</p>
</div>
</div>
</ol>
</div>
<!-- /block content -->
</div>
<!-- block header -->
</template>
Use a triple mustache {{{evt.details}}}, because by default Handlebars (or originally Mustache) escapes HTML.

Categories

Resources