MEAN js dynamic title - node.js

how to add dynamic title for each pages of the MEAN js application. in the layout.server.js has defined the title as follows.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{title}}</title>
so how can we make dynamic title?

Some people might be mislead thinking that besides it is already dynamic, it can be changed and it is controlled by angular out of the box because of having an expression with {{ }} but that's not quite true.
In fact {{title}} could mean an expression that should be evaluated against scope.title, however if you take a deeper look at MEAN.js you will see that it is using the swig template engine which also uses {{ }} to define variables. In this case, {{title}} is NOT an angular expression, it is a swig variable which was passed via express/swig and it can be changed in the config/env/default.js (in MEAN.js 0.4.0).
If you want the title to be changed in the frontend (i.e. possible to change it within angular logic) you have to assign a scope variable to the title element or use a custom directive. Even if, at first, the title value is the one defined using express/swig, angular can take control afterwards and change it accordingly to your needs.
One solution could be to define the title in your angular states like this:
.state('some-state', {
url: '/someurl',
templateUrl: 'some-path-to-view',
data: {
title: 'My new title',
}
})
And then listen for the $stateChangeSuccess event to set the title:
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
console.log(toState.data.title); // Prints the new title to the console
// Set the title
});
EDIT: First paragraph rewritten for more coherence.

To add to the accepted question, in the MeanJS stack you can do the following:
Create a new view in the modules/core/client/views ex. title.client.view.html.
In the file title.client.view.html you can get the title by doing:
<div ng-controller="HeaderController">
<span>{{$state.current.data.pageTitle}}</span>
</div>
The HeaderController has a $state variable that contains the current state title specified in:
.state('some-state', {
url: '/someurl',
templateUrl: 'some-path-to-view',
data: {
title: 'My new title',
}})
Then to get the title in the modules/core/server/views/layout.server.view.html file you include title.client.view.html like this:
<div ng-include="'/modules/core/client/views/title.client.view.html'"></div>
This will render the title of a state dynamically as you navigate.

The MEAN.JS page title is already dynamic and can be found at modules/core/client/directives/page-title.client.directive.js:
function listener(event, toState) {
var applicationCoreTitle = 'MEAN.js',
separator = ' - ',
stateTitle = applicationCoreTitle + separator;
Whereas 'MEAN.js' is the default page title and can be changed accordingly.

Related

Grails 3.3.9: Call controller action when checkbox is checked

I am fairly new to Grails and frameworks in general, so this is most likely a very basic problem. The only promising looking solutions I was able to find were working with the Tag, which is apparently deprecated in Grails 3. Similar questions do exist, but all from the time when was still a thing.
I am trying to program a way of displaying products that are grouped in subcategories which are then grouped in categories. When my page loads the subcategories and categories are requested from my database and selection options (Select-tag and checkboxes) are rendered in the view.
When one of the checkboxes representing the subcategories is checked i need to run a database query to get the product information and update an HTML-element by rendering a template for every row I get back. I have a controller action that does all that. My only problem is that I need a way to call the controller action whenever one of the checkboxes is checked.
I could maybe work around it by using actionSubmit and a hidden submit button that is clicked by javascript whenever a checkbox is checked, but that doesn’t seem like a proper solution.
I am probably missing some very basic functionality here but I did already thoroughly search and haven’t come across a proper solution by now, probably because I didn't use the right search terms. I would be so happy, if anyone could help me with this. Thanks a lot already!
The following example uses a javascript function activated in response to the checkbox being checked/unchecked, the value of which is passed to an action from which you can do whatever with the value of the checkbox, run your query etc. At present the action renders a template to update the view with the database results.
index.gsp
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<script type="text/javascript">
$(document).ready(function(){
$( '#cb' ).click( function() {
var checked = $(this).is(":checked");
$.ajax( {
url: "/yourController/yourAction?checked=" + checked,
type: "get",
success: function ( data ) {
$( '#resultDiv' ).html( data )
},
error: function(jqXHR, textStatus, errorThrown) {
console.log( 'Error rendering template ' + errorThrown )
}
} );
})
});
</script>
</head>
<body>
<div id="resultDiv"></div>
<g:form>
<g:checkBox name="cb" />
</g:form>
</body>
YourController
class YourController {
def yourAction() {
// you may want to do something with the value of params.checked here?
def dbResults = YourDomain.getStuff()
render ( template: 'theTemp', model: [dbResults: dbResults] )
}
}
_theTemp.gsp
<table>
<caption>Table of stuff</caption>
<g:each in="${dbResults}" var="aThing">
<tr>
<td>${aThing}</td>
</tr>
</g:each>
</table>

meteor with flow router layout is rendered twice

I don't know why but my layout is rendered two times.
Here is my index.html:
<head>
<title>title</title>
</head>
<body>
{{>layout}}
</body>
Here is my layout:
<template name="layout">
{{#if canShow}}
{{>Template.dynamic template=content}}
{{else}}
{{> loginButtons}}
{{/if}}
</template>
So here without route my template is display just one time.
Here is my route:
FlowRouter.route('/', {
action() {
BlazeLayout.render("layout", {
content: "home"
});
}
});
But with this route my template is display a second time.
This is my helpers, I think there is nothing to do with this problem but we never know.
Template.home.onCreated(function() {
this.autorun(() => {
this.subscribe('post');
});
});
Template.layout.helpers({
canShow() {
return !!Meteor.user();
}
});
Template.home.helpers({
cats() {
return Posts.find({});
}
});
you don't need to render layout in the body.
The router will take care of the rendering.
so, just have
<body>
</body>
or don't even have it at all.
Edit: Thanks to Keith, I have a better understanding of my problem. Here is his comment:
one thing to keep in mind, all the html you write in meteor isn't kept as html. It all gets converted to javascript. Things like index.html do not get pushed to the browsesr. Meteor just takes all the html you write converts it to javascript and renders what it needs to based on what your code says. This is how it knows todynamically change and rerender html
For things like changing title of the head or add meta etc, we can do it directely in the javascript.
ex: Meteor - Setting the document title

How to update an AngularJS directive when using $route and partials

http://jsfiddle.net/MTzJF/36/
The JSFiddle above is set up to explain the issue. But, basically:
HTML:
<breadcrumb></breadcrumb>
<div ng-view></div>
Angular Directive & Routing:
angular
.module('app', [])
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul>",
replace: true,
controller: Ctrl1
}
})
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
template: '<h1>{{pgTitle}}</h1>',
controller: Ctrl2
});
}]);
Controllers
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
function Ctrl2($scope, $routeParams) {
$scope.path = [{
label: 'Home',
url: '#/'},{
label: 'Node 2',
url: '#/node2'}];
$scope.pgTitle = "Node 2"
}
​
I expect that changing $scope.path in Ctrl2 will update the breadcrumb directive, but it's not happening. I have to believe it has something to do with their relative scopes, but simply don't understand it well enough to see what. I've read dozens of articles and StackOverflow posts on it, but nothing is specific enough to let me see what I'm missing.
I'm hoping someone can point me in the right direction.
Thanks much!
nz
The reason your fiddle is not working is because ( like you rightly identified ) of scope issue. Your Ctrl1 is the Controller that controls the scope for your directive. The directive is looking for a variable called path which is an array of path's. If we have a look at the path variable in that scope it seems to be containing just 1 value inside of it.
function Ctrl1($scope) {
$scope.path = [{
label: 'Home',
url: '#/'}];
$scope.pgTitle = "Home"
}
Now you wish to change this variable path in another controller Ctrl2. I am assuming that you are attempting to have the scope of Ctrl2 "inherit" from the scope of Ctrl1. To achieve this, first check on which element Ctrl2 is defined. Is that element ( html element ) a child of the element of Ctrl1 ?
From your HTML :
Element of Ctrl1 : <breadcrumb></breadcrumb>
Element of Ctrl2 : <div ng-view></div>
For Ctrl2 to be child of Ctrl1 : your HTML structure should look like :
<breadcrumb>
<div ng-view></div>
</breadcrumb>
If we make this change to your code, it doesnt work yet. This is because when angular looks at the directive for <breadcrumb> it has no idea what it should do with the stuff that is inside of that node. <breadcrumb> is a html node. Since it is a node, it can contain content / other nodes inside of it. When you replace this breadcrumb node with the template, you should also give angular instructions to the effect : "If you find stuff inside of me, put it here". This is how you do it.
Modify your directive code to be :
.directive('breadcrumb', function() {
return {
restrict: 'E',
template: "<div><ul class='breadcrumb'><li ng-repeat='node in path'><a ng-href='{{node.url}}'>{{node.label}}</a></li></ul><div ng-transclude></div></div>",
replace: true,
transclude : true,
controller: Ctrl1
}
})
There are few differences / changes here.
Added an attribute called transclude to the directive object and set it to true.
Wrap the whole template so that it can be returned as a single HTML element.
Specify the place where you want the contents of the to go. Notice the ng-transclude. That is the place where the contents go.
You will notice now that the content is getting replaced now. Except the path is not getting updated with the path value from the child controller. Have a look at this https://stackoverflow.com/a/14049482/1057639 answer. It is an amazing explanation of scope / prototypical inheritance. Basically, your write to path is creating a new path variable in the child scope that is overshadowing the parent path ( which is being used by the directive).
Your best bet in this scenario is to create an addPath function in the parent scope and use it ( in child scopes ) to add new Path when you define new subviews.
Here is a fiddle that does all these.

How to render a YUI datatable?

Following the documentation of the YUI DataTable control i've inferred the following code:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<SCRIPT type="text/javascript" src="http://yui.yahooapis.com/3.5.1/build/yui/yui-min.js"></SCRIPT>
<SCRIPT type="text/javascript">
// Create a new YUI instance and populate it with the required modules.
YUI().use('datatable', function (Y) {
// Columns must match data object property names
var data = [
{ id: "ga-3475", name: "gadget", price: "$6.99", cost: "$5.99" },
{ id: "sp-9980", name: "sprocket", price: "$3.75", cost: "$3.25" },
{ id: "wi-0650", name: "widget", price: "$4.25", cost: "$3.75" }
];
var table = new Y.DataTable({
columns: ["id", "name", "price"],
data: data,
// Optionally configure your table with a caption
caption: "My first DataTable!",
// and/or a summary (table attribute)
summary: "Example DataTable showing basic instantiation configuration"
});
table.render("#example");
});
</SCRIPT>
</HEAD>
<BODY>
</BODY>
</HTML>
The insulting thing is that the documentation says:
This code produces this table:
except that this code produces this table:
So obviously i'm missing something pretty fundamental about how to render a YUI data table. What is the correct way to render a YUI data table?
Q. How to render a YUI datatable?
Another page mentions including a <div>, changing my <BODY> from empty to:
<BODY>
<div class="example yui3-skin-sam">
<div id="simple"></div>
<div id="labels"></div>
</div>
</BODY>
but does not change the look of the control.
Add class="yui3-skin-sam" in body tag, table css is written corresponding to this class.
Move the <script>s to the bottom of the <body>, or at least after the <div> that will contain the DataTable. That will avoid a race condition where the scripts may be loaded before the DOM is set up.
render('#example') is telling the DataTable to render into an element with an id of 'example' The markup sample you included has a div with a class of 'example', then two divs with ids 'simple' and 'labels'. You need to make sure you're rendering inside a parent element with class yui3-skin-sam. If you tell a YUI widget to render into an element it can't find, it falls back to rendering it inside the <body>. You can fix this in a few ways:
add the class to the <body> tag instead of a <div> (not a bad idea, but you should still fix the render target selector)
use a render(?) target selector that matches an element on the page, such as render('.example'), render('#simple'), or render('#labels').
In any case, make sure your render target is inside an element with class="yui3-skin-sam"

How do you post data to CouchDB both with and without using JavaScript

I have a show which displays a form with fields populated from a document. I'd like to change the values in the field and then save the updated document.
I'm having trouble finding a clear, concise example of how to do this.
Seriously, just finishing this example would work wonders for so many people (I'm going to leave a lot of stuff out to make this concise).
Install Couchapp
This is outside the scope of my question, but here are the instructions for completeness.
Create a couchapp
Again, this is kind outside the scope of my question. Here is a perfectly concise tutorial on how to create a couchapp.
Create a template
Create a folder in the root of your couchapp called templates. Within the templates folder create an HTML page called myname.html. Put the following in it.
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<form method='post' action='#'>
<fieldset>
Hello <input type='text' name='name' value='{{ name }}'>
<input type='submit' name='submit' value='submit'>
</form>
</body>
</html>
Create a show
See the tutorial above for hwo to do this.
Add this code to a show called myname.
function(doc, req) {
if (doc) {
var ddoc = this
var Mustache = require("vendor/couchapp/lib/mustache");
var data = {
title: "The Name",
name: "Bobbert"
}
return Mustache.to_html(ddoc.templates.myname, data)
} else {
return ('nothing here baby')
}
}
Update the document with a new name by ...
So who can complete this step via both the client side and the server side?
Please don't point me to the guide, I need to read it in your words.
Thanks.
Edit:
Although the return value isn't pretty, just posting a form to the update handler will update the document.
You will probably want to look into update handler functions.
An update handler handles granular document transformations. So you can take 1 form, that has one distinct purpose, and only update the relevant fields in your document via the update handler.
Your update handler will need to take a PUT request from your form. A browser can't do this directly, so you'll need some javascript to handle this for you. If you're using jQuery, this plugin can take your form and submit it seamlessly via AJAX using PUT for you.
Inside the function, you can take the fields you are accepting, in this case name and apply that directly to the document. (input validation can be handled via the validate_doc_update function)
Update Handler (in your Design Document)
{
"updates": {
"name": function (doc, req) {
doc.name = req.form.name;
return [doc, "Name has been updated"];
}
}
}
HTML
<form id="myForm" action="/db/_design/ddoc/_update/name/doc_id">...</form>
JavaScript
$(document).ready(function() {
$('#myForm').ajaxForm({
type: "PUT",
success: function () {
alert("Thank you");
}
});
});
Once you've gotten this basic example up and running, it's not much more difficult to add some more advanced features to your update handlers. :)

Resources