I have a website using Sammy and Knockout. I am trying to route multiple views to different URLs with Sammy but I'm having some difficulty. I need to pass the data parameter as well as the templateName parameter. How would I be able to pass the data parameter? I've included relevant code below.
Javascript
var View = function (title, templateName, data) {
var self = this;
this.title = title;
this.templateName = templateName;
this.data = data;
};
var viewModel = {
views: ko.observableArray([
new View("Home", "home", homeView),
new View("Announcements", "announcements", announcementView),
new View("Calendar", "calendar", monthView),
new View("Contact Us", "contactus", contactView),
new View("Events", "events", eventsView)
]),
selectedView: ko.observable()
};
$.sammy(function () {
this.get('#:templateName', function () {
viewModel.selectedView(this.params);
});
}).run('#home');
vbhtml
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="#">Events</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav" data-bind="foreach: views">
<li data-bind="css: {active: $root.selectedView == $data"><a data-bind= "text: title, click: $root.selectedView " ></a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>Login</li>
</ul>
</div>
</div>
</nav>
<div data-bind="with: selectedView">
<div data-bind="template: { name: templateName, data: data }"></div>
</div>
<script id="home" type="text/html">...</script>
<script id="announcements" type="text/html">...</script>
<script id="calendar" type="text/html">...</script>
<script id="contactus" type="text/html">...</script>
Use the context parameter passed into the get's callback function
this.get('#:templateName', function(context) {
var params = context.params;
});
You should then be able to append querystring params and read them from the get function.
.run('#home?param1=1¶m2=2')
Related
I have a problem with google geocode suggest. I have a modal which show a form to complete an address. I have implemented geocode to make easier the address filling, but the suggest is appearing behind the modal, like this:
Some code over here:
JS which implements geocode:
GoogleGeocode = (function () {
var _api = {};
var _googleApiRetrievedOk = false;
var _autocompleteEvent;
var _addressInputId, _zipCodeInputId, _countryInputId, _countryComboboxId;
var _componentToRetrieve = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function loadGoogleApis() {
// Importar fuentes
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', 'https://fonts.googleapis.com/css?family=Roboto:300,400,500'));
// Importar api Places
$('head').append($('<script type="text/javascript" />').attr('src', 'https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places&callback=GoogleGeocode.GoogleGeocodeInit'));
}
function googleGeocodeInit() {
_googleApiRetrievedOk = true;
}
$(document).ready(loadGoogleApis);
return _api;
})();
View which supports modal:
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-footer">
<div class="col-md-6 col-md-offset-1">
<h2>#T("StudentData")</h2>
</div>
<button type="button" class="btn btn-CTA" data-dismiss="modal">X</button>
</div>
<div class="modal-header">
#Html.Action("PrepareStudentDataModel", "Topic")
</div>
</div>
Part of view which calls google geocode:
<div class="form-group row">
<div class="col-md-12">
#Html.TextAreaFor(model => model.Address1, new { #class = "form-control", placeholder = #T("wke.checkout.StudentAddress.geocodeaddress") })
#Html.ValidationMessageFor(model => model.Address1)
<span class="col-md-6 col-xs-6 field-validation-valid" id="StudentAddress_address1MessageValidation" style="visibility: hidden;">
#T("wke.checkout.StudentAddress.messagevalidation")
</span>
</div>
</div>
I am a newbie in MeteorJS. I tried to do list with download and report buttons:
List template:
<template name="myBooks">
<div class="container">
<h2>My books</h2>
<div class="list-group">
{{#each myBooks}} {{> myBookListItem}} {{/each}}
</div>
</div>
</template>
myBookListItem Template:
<template name="myBookListItem">
<a class="list-group-item">
<span class="badge badge-success">{{downloads}}</span>
<span class="badge badge-error">{{warnings}}</span>
<h4 class="list-group-item-heading "><i>{{title}}</i> - {{author}}</h4>
<p class="list-group-item-text ">{{description}}</p>
<button type="submit" id="download" class="btn btn-success">Download</button>
<button type="submit" id="report" class="btn btn-danger">Report</button>
</a>
</template>
My book collection item contains also "link" property which is url to downloadable pdf - how can I access it on #download button click?
if (Meteor.isClient) {
Template.myBookListItem.events({
'click #download': function (event) {
//What_kind_of_magic_shoud_i_use_here()
alert();
},
'click #report': function (event) {
alert();
},
});
}
Anybody can help me:)?
I just needed to use this.link.
I have an angular app that has the following ng-repeat:
<div ng-repeat="detail in mpttdetails">
<div ng-if="detail.category.id == {{node.id}}" class="list-group">
{%verbatim%}
<li class="list-group-item" >
<div class="row">
<div class=".col-lg-2 col-md-2 col-sm-2">
{{detail.student_academic_credit.course_name}}
</div>
<div class=".col-lg-4 col-md-4 col-sm-3">
{{detail.student_academic_credit.title}}
</div>
<div class=".col-lg-2 col-md-2 col-sm-2">
{{detail.student_academic_credit.credit}}
</div>
<div class=".col-lg-2 col-md-2 col-sm-2">
{{detail.student_academic_credit.final_grade}}
</div>
<div class=".col-lg-2 col-md-2 col-sm-3">
{{detail.student_academic_credit.term}}
</div>
</div>
</li>
{%endverbatim%}
</div>
</div>
My mpttservice here is a service that fetches data from a django app. Here i would like to have a bootstrap badge as:
<span class="badge badge-info">{{sum}}</span>
just above the ng-repeat such that it adds all the {{detail.student_academic_credit.credit}} from the list. How do i achieve this since all the details are inside the ng-repeat??
I suggest you use a couple of filters: Angular's filter for filtering details based on their categoryId and one custom filter for summing credits.
app.filter('sumCredits', function () {
return function (details) {
var sum = 0;
details.forEach(function (item) {
sum += item.student_academic_credit.credit;
});
return sum;
};
});
<span class="badge badge-info"
ng-bind="mpttdetails | filter:{catagory:{id:node.id}} | sumCredits">
</span>
<div ng-repeat="detail in mpttdetails | filter:{catagory:{id:node.id}}">
{%verbatim%}
<li class="list-group-item">
...
See, also, this short demo.
In the controller that has the service injected, loop through just like ng-repeat is doing and add to your $scope.sum.
app.controller('WhateverCtrl', function($scope, mptt) {
// Assuming it's an ajax call
mptt.getDetails().success(function(mpttdetails) {
$scope.mpttdetails = mpttdetails;
// Set sum on scope
var sum = 0;
angular.forEach(mpttdetails, function(detail) {
sum = sum + detail.student_academic_credit.credit;
});
$scope.sum = sum;
});
});
In this example I want to use knockout.js to allow the "Expand" link to be clicked and have its text changed to "Collapse". I also want to set the make the jobDetails section visible. This is a very general question of how to get knockout.js to specifically modify the DOM of the "current" item in a list using a click handler.
<script type="text/html" id="job-template">
<div class="jobContainer">
<label data-bind="text: JobTitle"></label>
<label data-bind="text: CompanyName"></label>
<div class="jobDetails">
<label data-bind="text: City"></label>
<label data-bind="text: State"></label>
</di>
<div>
<a class="expand" href="#" data-bind="click: ???">Expand</a>
</div>
</div>
</script>
This is very straight forward with KO. Here's a simple way to do it. FYI I had to fix your markup slightly.
<div>
<div class="jobContainer">
<label data-bind="text: JobTitle"></label>
<label data-bind="text: CompanyName"></label>
<div class="jobDetails" data-bind="visible: expanded">
<label data-bind="text: City"></label>
<label data-bind="text: State"></label>
</div>
<div>
<a class="expand" href="#" data-bind="click: toggle, text: linkLabel">Expand</a>
</div>
var viewModel = function() {
this.JobTitle = ko.observable("some job");
this.CompanyName = ko.observable("some company");
this.City = ko.observable("some city");
this.State = ko.observable("some state");
this.someValue = ko.observable().extend({ defaultIfNull: "some default" });
this.expanded = ko.observable(false);
this.linkLabel = ko.computed(function () {
return this.expanded() ? "collapse" : "expand";
}, this);
this.toggle = function () {
this.expanded(!this.expanded());
};
};
http://jsfiddle.net/madcapnmckay/XAzW6/
Hope this helps.
i'm learning EmberJS and building a comment section that allows 1 level of sub comments. I have an Ember View listing all the comments, when you click "reply" on a particular comment, it should display a textarea input for a user to write a sub-comment.
In my EmberJS code when you click "reply" it shows the textarea input for all the comments not just the specific one. Any advice would be appreciated :)
// View
App.commentsView = Em.View.create({
templateName: 'commentsTmpl',
showReply: false,
reply: function(e) {
e.view.set('showReply', true);
e.preventDefault();
}
});
App.replyCommentsView = Em.View.extend({
showReplyBinding: 'App.commentsView.showReply'
});
// Template
<script data-template-name="commentsTmpl" type="text/x-handlebars">
</h2>comment</h2>
{{#each App.commentsController}}
<div class="comment-group clearfix">
<div class="comment">
<img class="comment-pic" {{bindAttr src="userPic"}} alt="user pic">
<div class="comment-content">
{{userName}}
<span class="comment-body">{{text}}</span>
<div class="comment-actions clearfix">
<a href="#" {{action "reply"}}>Reply</a>
</div>
</div>
</div>
{{#view App.replyCommentsView}}
{{#if showReply}}
<div class="comment-reply">
<h2>sub-comment</h2>
<textarea class="txt-comment-reply" rows="2" cols="65"></textarea>
</div>
{{/if}}
{{/view}}
</div>
{{/each}}
</script>
Currently you are binding the showReply to App.commentsView which is the whole container. To be make it easy activate single comments, I'd suggest looking into a CollectionView, this way each of your comments will have their own view and you can toggle showReply on an individual comment's view.
Something like this: (Sorry, I haven't tested it)
App.commentsView = Em.View.create({
templateName: 'commentsTmpl'
});
App.CommentView = Em.View.extend({
classNames: "comment-group clearfix".w(),
showReply: false,
reply: function(e) {
e.preventDefault()
this.set("showReply", true)
}
})
// Template
<script data-template-name="commentsTmpl" type="text/x-handlebars">
</h2>comment</h2>
{{#collection contentBinding="App.commentsController" itemViewClass="App.CommentView"}}
<div class="comment">
<img class="comment-pic" {{bindAttr src="content.userPic"}} alt="user pic">
<div class="comment-content">
{{content.userName}}
<span class="comment-body">{{content.text}}</span>
<div class="comment-actions clearfix">
<a href="#" {{action "reply"}}>Reply</a>
</div>
</div>
</div>
{{#if showReply}}
<div class="comment-reply">
<h2>sub-comment</h2>
<textarea class="txt-comment-reply" rows="2" cols="65"></textarea>
</div>
{{/if}}
{{/each}}
</script>