how to render the contents of a template .. i can;t pass through this point :/ thanks for your help
example :
<body>
{{> dash}}
</body>
<template name="dash">
<div id="example2" class='example_block'>
<form name = "frm">
<table>
<tr>
<td>Template Name
<td>:
<td><input type="text" name = tname class = "tname">
</frm>
<div class='demo'>
<input type='button' value='Click Here to Create Window' class="btn"/>
</div>
</div>
<div id = "window_block8" style="display:none;"></div>
</template>
<template name="t1">
try1
</template>
<template name="t2">
try2
</template>
//client.js
Template.dash.events({
'click input.btn' : function(){
var temp = document.frm.tname.value ;
Session.set("template" , temp);
$('body').append(Meteor.render(Template[Session.get("currentTemplate")]()));
}
});
some thing like this.. but that code wont work on me
Meteor.render(Template.try) returns a document fragment which you can insert into your page with jQuery or vanilla JS.
e.g
Template.dash.aw = function() {
document.body.appendChild(Meteor.render(Template.try));
}
Note that you can use array-style notation if the template name is variable:
document.body.appendChild(Meteor.render(Template[Session.get("currentTemplate")]));
Alternatively, if you only want to return a variable and not an entire template:
Template.try.var = function() {
return 'Hello';
}
Template.dash.aw = function() {
return Template.try.var();
}
// Template.dash.aw = Template.try.var = function() {
// return 'Hello';
// }
The commented function is probably inadequate, since you want some logic in Template.dash.aw
Related
I am trying to implement text formatting on a string called name.Once the string is entered into the html form,upon click of a save button, the new string format should be rendered below the form.
The string should either be changed to uppercase or lowercase depending on string length.
If string length is even,the string should be changed to uppercase, if string length is odd,string should be changed to lowercase.
I have put the logic for changing the text case inside the 'formatFactory' factory.The format method inside the 'formatFactory' is responsible for changing text case.
formattingFactory.js
app.factory('formatFactory', function(){
var formattingFactoryObject = {};
formattingFactoryObject.format = function(name) {
if(name.length % 2 == 0) {
name.toUpperCase();
}else{
name.toLowerCase();
}
}
});
I have the following service that is responsible for saving session data i.e name and nickname strings
sessionService.js
angular.module('app').service('sessionService',[
'$window',
//the $window object provides angular access to the browser's window object
sessionService
]);
function sessionService($window) {
this.save = save;
this.get = get;
this.clear = clear;
function save(key, value) {
$window.sessionStorage.setItem(key, value);
}
function get(key, value) {
return $window.sessionStorage.getItem(key);
}
The following is my controller.I have called the method for changing string case right before the method for saving session data inside vm.setServiceSession method
sessionController.js
angular.module('app').controller('sessionController',[
'sessionService','formatFactory',
function sessionController(sessionService) {
var vm = this;
vm.getServiceSession = function() {
vm.model = {
name: sessionService.get('name'),
nickname: sessionService.get('nickname'),
status: 'Retrieved by service on ' + new Date()
};
}
vm.setServiceSession = function() {
formattingFactoryObject.format(name);
sessionService.save('name', vm.model.name);
sessionService.save('nickname', vm.model.nickname);
vm.getServiceSession();
}
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Services and Factories</title>
<link rel="stylesheet" href="./css/bootstrap.min.css">
</head>
<body ng-controller="sessionController as vm">
<div class="container">
<h1>Services and Factories</h1>
<div class ="form-group row">
<div class ="col-sm-4">
<label>Name</label>
</div>
<div class ="col-sm-8">
<input type = "text" class ="form-control" ng-model ="vm.model.name">
</div>
</div>
<div class ="form-group row">
<div class ="col-sm-4">
<label>Nickname</label>
</div>
<div class ="col-sm-8">
<input type = "text" class ="form-control" ng-model ="vm.model.nickname">
</div>
</div>
<div class = "form-group row">
<div class = "col-sm-8 col-sm-offset-4">
<input type = "button" ng-click = "vm.setServiceSession()" class = "btn btn-primary" value = "Save"/>
<input type = "button" ng-click ="vm.getServiceSession()" class = "btn btn-default" value = "Retrieve from Service"/>
</div>
</div>
<pre>{{vm.model | json }}</pre>
</div>
The problem with the above code is that it doesnt change the string case and i cant figure out why.
You need to assign the new value of name.toLowerCase() and name.toUpperCase() to a new value name as #Rajesh said in his comment, and of course return name in the end in your factory. You also have to format the $scope.model.name while saving it in the localStorage like this :
sessionService.save('name', formatFactory.formattingFactoryObject($scope.model.name));
You also need to refactor your factory.
I created a working Fiddle.
Having trouble setting clearing input field
I’m currently trying to clear the input box on ng-model="newInstruction.instructionText" after an new instruction text has been added. Here is the code where I tried to reset it to empty string but input field didn't clear. Why is that?
I’ve tried console logging the following in updateInstructionText function:
Console.log (newInstruction) returns undefined in console.
Console.log ($scope.newInstruction) returns undefined in console.
Console.log (instruction) returns a object with instruction text inside ex: Object {instructionText: ‘new instruction’}
Controller:
angular.module('app').controller('InstructionController', function($scope, $http, NgTableParams, $filter) {
$scope.initList = function() {
$scope.getRemoteInstructions = function(typed) {
$http.get("/api/instructions?searchInstructionText=" + typed).then(function(response) {
$scope.instructionChoices = _.map(response.data, function(instruction) {
instruction.instructionText;
});
});
};
$scope.updateInstructionText = function(instruction) {
var instructionPromise;
if (instruction.id) {
instructionPromise = $http.put("api/instructions/" + instruction.id, instruction);
}
else {
instructionPromise = $http.post("/api/instructions", instruction);
}
$scope.newInstruction = '';
$instruction = '';
instructionPromise.then(function(response) {
$('#instructionModal').closeModal();
$scope.instructionTable.reload();
});
};
};
});
HTML
<div class="container-fluid" ng-init="initList()">
<div class="row">
<h3>Total Instructions: {{totalInstructions}}</h3>
<table class="striped highlight bordered" ng-table="instructionTable" show-filter="true">
<tr>
<td class="input-field">
<input placeholder="Enter New Instruction Text" ng-model="newInstruction.instructionText" type="text">
</td>
<td>
<a class="waves-effect waves-light btn" ng-click="updateInstructionText(newInstruction)">Add</a>
</td>
</tr>
</table>
</div>
</div>
<ng-include src="'/views/modals/instructionModal.html'"></ng-include>
</div>
Simply do:
instruction.instructionText = null
Since you are accessing the argument (object) inside the function with name instruction, if you set this to null, you can clear the input field
Simply do
$scope.newInstruction.instructionText=null
I have an table element where the declaration is as follows
<euro-table id="euroTable" number-visible-rows="10">
<euro-column title="Id" type="text" key="Id"></euro-column>
<euro-column title="Descripcion" type="text" key="Descripcion"></euro-column>
<euro-column title="Abreviatura" type="text" key="ShortName"></euro-column>
<euro-column title="Tipo" type="object" key="FeeType" objectkey="Descripcion"></euro-column>
<euro-column title="Monto($)" type="text" key="Monto"></euro-column>
<euro-column title="Cobrar a" type="array" key="NivelesEscolares" objectkey="Descripcion"></euro-column>
</euro-table>
Data is added using javascript after an iron-ajax request. Everything works as it should work, except for one thing: when I use dom-repeat to bind added data I use <dom-if> template because depending on the type of column, I must access and display the corresponding information. The code I use to do that is the following:
<template is="dom-repeat" items="{{visibleRows}}" id="tableRow" as="row">
<tr on-tap="rowSelected" class$="{{getClass(item.active)}}">
<template is="dom-repeat" items="{{headers}}" id="tableRow2" as="column">
<template is="dom-if" if="{{getType(column.type, 'object')}}">
<td>
<li>{{getObjectValue(column,row)}}</li>
</td>
</template>
<template is="dom-if" if="{{getType(column.type, 'array')}}">
<td>
<template is="dom-repeat" items="{{getDataArray(column,row)}}">
<li>{{getObjectValue(column,row)}}</li>
</template>
</td>
</template>
<template is="dom-if" if="{{getType(column.type, 'text')}}">
<td>{{getValue(column,row)}}</td>
</template>
</template>
</tr>
</template>
So my problem is that I can not display the information correctly and I think the reason is for the use of dom-repeat. My information is displayed as follows:
The information is out of the table, I'm a checking my getType function but I think its ok. Any idea about to fix my bug? Thanks!
After I had researched a little more, I found here that my problem was a bug of polymer. To solve it, is necessary to change two functions in Polymer.html file. The functions are _wrapTextNodes and _showHideChildren. I will leave the functions here just in case anyone have the same problem.
_wrapTextNodes: function(root) {
// wrap text nodes in span so they can be hidden.
for (var n = root.firstChild; n; n=n.nextSibling) {
if (n.nodeType === Node.TEXT_NODE && n.textContent.trim.length) {
var s = document.createElement('span');
root.insertBefore(s, n);
s.appendChild(n);
n = s;
}
}
},
_showHideChildren: function() {
var hidden = this._hideTemplateChildren || !this.if;
if (this._instance) {
var c$ = this._instance._children;
for (var i=0; i<c$.length; i++) {
var c = c$[i];
if (c.nodeType !== Node.TEXT_NODE) {
c.style.display = hidden ? 'none' : '';
c._hideTemplateChildren = hidden;
}
}
}
},
Here you can find dom-if.html file.
I want to toggle my 2 on & off images when I click on my lightbulb. Sometimes it seems to work and other times it does not. I cant get the ng-click to work at all unless I use ng-repeat and at least two images. How do I best accomplish toggling the images for 1 lightbulb? Is there any way to synchronize the checkbox so that when it is checked the light goes on and when it is off the light goes off? (I am new to javascript)Here's the fiddle:
Fiddle
<body ng-app="myApp">
<div ng-controller="MyCtrl">
lightbulb is {{state}} <input type="checkbox" ng-model=
"state" ng-true-value="on" ng-false-value="off">
<div ng-repeat="image in images">
<a ng-click="toggleImage(image)">
<img ng-src="{{image.imgUrl}}" />
</a>
</div>
</div>
function MyCtrl($scope) {
//$scope.checkboxState = "off";
//$scope.resetUrl = 'http://www.w3schools.com/js/pic_bulboff.gif';
$scope.state = "on";
$scope.onUrl = 'http://www.w3schools.com/js/pic_bulbon.gif';
$scope.offUrl = 'http://www.w3schools.com/js/pic_bulboff.gif';
$scope.images = [
{imgUrl: 'http://www.w3schools.com/js/pic_bulboff.gif'},
{imgUrl: 'http://www.w3schools.com/js/pic_bulbon.gif'},
];
$scope.toggleImage = function (image) {
if (image === $scope.offUrl) {
image.imgUrl = $scope.onUrl;
} else {
image.imgUrl = $scope.offUrl;
}
};
}
The easiest way to toggle something is to store the state in your scope and then render based on that. Right now you have a lot of extraneous code that could be eliminated. I would restructure your code to something like:
function MyCtrl($scope) {
$scope.onUrl = "pic_bulbon.gif";
$scope.offUrl = "pic_bulboff.gif";
$scope.isBulbOn = false;
$scope.bulbText = function() { return $scope.isBulbOn ? "on" : "off"; };
$scope.bulbUrl = function() {
return $scope.isBulbOn ? $scope.onUrl : $scope.offUrl;
};
}
<body ng-app="myApp">
<div ng-controller="MyCtrl">
lightbulb is {{ bulbText() }}
<input type="checkbox" ng-model="isBulbOn">
<a ng-click="isBulbOn = !isBulbOn">
<img ng-src="{{ bulbUrl() }}" />
</a>
</div>
</body>
You can check out the Fiddle here: http://jsfiddle.net/UYaLJ/
There was an issue with the ifcondition. The ng-repeat works on the JSON object. Hence, the function parameter 'image' is an object. The correct if statement is as follows:
if (image.imgUrl === $scope.offUrl) {
I have updated the fiddle. URL is:http://jsfiddle.net/7857c/1/
The goal
Read content from DOM element with KnockoutJS.
The problem
I have a list of products in my HTML. The code is something like this:
<li>
<div class="introduction">
<h3>#Model["ProductName"]</h3>
</div>
<form data-bind="submit: addToSummary">
<input type="number"
placeholder="How much #Model["ProductName"] do you want?" />
<button>Add product</button>
</form>
</li>
When I click on <button>Add Product</button>, I want to send to KnockoutJS the text inside <h3></h3> of the element that was submitted.
The file to work with KnockoutJS is external and independent of HTML. It name is summary.js and the code is below:
function ProductReservation(id, name, unity, quantity) {
var self = this;
self.id = id;
self.name = name;
self.unity = unity;
self.quantity = quantity;
}
function SummaryViewModel() {
var self = this;
self.products = ko.observableArray([
new ProductReservation(1, "Testing", "kgs", 1)
]);
self.addToSummary = function () {
// Do Something
}
}
What I'm thinking about
HTML:
<li>
<div class="introduction">
<h3 data-bind="text: productName">#Model["ProductName"]</h3>
</div>
[...]
</li>
JS:
productName = ko.observable("text: productName");
But, of course, no success — this is not the correct context or syntax, was just to illustrate.
So I ask: what I need to do?
You're binding addToSummary via the submit binding. By default KO sends the form element to submit-bound functions.
So addToSummary should have a parameter -
self.addToSummary = function (formElement) {
// Do Something
}
You can pass additional parameters to this function (as described in KO's click binding documentation under 'Note 2'), or you could just add a hidden field to your form element and pull it from there.
<li>
<div class="introduction">
<h3>#Model["ProductName"]</h3>
</div>
<form data-bind="submit: addToSummary">
<input type="number" name="quantity"
placeholder="How much #Model["ProductName"] do you want?" />
<input type="hidden" name="productName" value="#Model["ProductName"]" />
<button>Add product</button>
</form>
</li>
Then in your knockout code you could use jQuery to process the form element to pull out the data -
self.addToSummary = function (formElement) {
var productName = $(formElement).children('[name="productName"]')[0].val();
var quantity= $(formElement).children('[name="quantity"]')[0].val();
// ...
self.products.push(new ProductReservation(?, productName, ?, quantity));
}
One strategy that has worked well in my experience is to implement a toJSON extension method that serializes your model (if you use a library like JSON.NET you can have a lot of control over what gets serialized and what does not).
Inside of the view where you initialize KnockoutJS, you could serialize your model and pass it into the KnockoutJS ViewModel you're creating (assuming :
Main view:
<script type="text/javascript">
var viewModel = new MyViewModel(#Model.ToJSON());
</script>
ViewModel:
function MyViewModel(options) {
this.productName = ko.observable(options.ProductName);
}