display custom angular script template as table detail row - javascript

Hi i am quite new to angular programming and I had a question on hwo to include angular script templates into a table
Basically I have a base directive table that displays data, but I want anyone who uses that base directive to provide a template of how they want the detail row to look like. I thought the best way to do this was from an "angular script template"
This fiddle describes what I want to do:
http://jsfiddle.net/g0b1xk9s/1/
Basically in the fiddle I was wondering if it was possible to display the template with id (template1) where I have the code
<div ng-include src="template1">
</div>
Is this possible or should I find another way to do this?
Thank you for the help

Sure you can and script tags are documented as a valid template approach
<div ng-include src="'template'"></div>
<script type="text/ng-template" id="template">
<table border="1">
<tr ng-repeat="note in ctrl.notes">
<td>{{note.label}}</td>
</tr>
<tr ng-repeat-end>
<td>Done: {{note.done}}</td>
</tr>
</table>
</script>
DEMO

Related

Nested StimulusJS scopes / controller issue / HTML 5 template tag

I have a basic Rails app with a nested association and I am doing a standard 'line items' type view where I am dynamically adding and removing rows from a template tag. I have a select that triggers a AJAX call to replace all the nested row selects (the context changed). The expenditure controller handles the overall form and the nested-form controller is used on other pages to handle the adding and removal of rows:
<div data-controller="expenditure nested-form">
<select data-target="expenditure.budget" data-action="change->expenditure#update_related"></select>
<table>
<thead></thead>
<tbody>
inserted rows...
<tr>
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
<template data-target="nested-form.template">
<tr data-new_record="true">
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
</template>
</tbody>
</table>
</div>
It works fine. I can add and remove rows and if I change the expenditure.budget select all the expenditure.budgetItemSelect targets get updated EXCEPT for the one inside the template. It's as if it's missing from the entire scope of the controller. I had them nested before but now have them in the same div data-controller="expenditure nested-form" to double check and it still doesn't work. Checked spelling and even tried removing the data-target="nested-form.template". No errors in the browser console. Am I missing something obvious here?
UPDATE
Hmmm... it seems that the template tag is read only and NOT part of the DOM which is why this fails.
I managed a hack where I replaced the contents of the entire template but that seems to break the controller that adds / deletes the rows 🤦‍♂️.
UPDATE 2
I found a workaround - If someone can improve this code I will accept this as a better answer.
It seems to be an issue with the <template> tag in HTML5.
I have a workaround but it's ugly.
<div data-controller="expenditure nested-form">
<select data-target="expenditure.budget" data-action="change->expenditure#update_related"></select>
<table>
<thead></thead>
<tbody>
inserted rows...
<tr>
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
<template id="expenditure_items_template">
<tr data-new_record="true">
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
</template>
<script type="text/template" data-target="nested-form.template" id="expenditure_items_template_script">
</script>
</tbody>
</table>
</div>
Here is what I did in my controller:
// find the template
var template = document.getElementById("expenditure_items_template");
// load the template contents
var new_template = document.importNode(template.content, true);
// replace the select with my new content (off screen)
new_template.getElementById('expenditure_expenditure_items_attributes_NEW_RECORD_budget_item_id').innerHTML = select.innerHTML;
// clear the new script place holder
document.getElementById("expenditure_items_template_script").innerHTML = "";
// set the new updated template into the script tag
document.getElementById("expenditure_items_template_script").appendChild(new_template);
I basically have two templates - one <template> which holds the raw HTML and the second <script> that works with Stimulus.

loading common templates into an html page with angular

I have a page which contains detail sections that are common across multiple pages of my app. I am trying to reduce code redundancy and create these mini views that will be loaded with the page.
In the main detail page I have a section that I am trying to load using ng-include
<div ng-show="checkProducts()">
<hr style="margin-bottom:5px!important"/>
<p><strong><em>Products</em></strong></p>
<div class="bs-associationPanel">
<ng-include src="commontemplates/productView/shoes"></ng-include>
</div>
</div>
I can't use routing here as this is acting like a partial view within the main detail page which is already using routes to load it and bind it to the controller.
The src value is a path in the APP to an html page called productView.html
I wrapped it in a script ng-template tag with an id
<script type="text/ng-template" id="shoes">
<table class="table table-condensed table-responsive">
<thead>
<tr>
<th>brand</th>
<th>color</th>
<th>size</th>
</tr>
</thead>
<tbody ng-repeat="s in detail.shoes">
<tr>
<td>{{s.brand}}</td>
<td>{{s.color}}</td>
<td>{{s.size}}</td>
</tr>
</tbody>
</table>
</script>
I was hoping this would work but when I render the page I get no temple and looking at the element explorer I see the following
<!-- ngInclude: undefined -->
I think I am close I just don't know what I am missing. Any suggestions on how this could be accomplished or Can this be accomplished?
Basically the script's with type text/ng-template are read by angular & angular consider it as template then put those templates inside $templateCache service for faster retrieval.
src attribute should have template name enclosed with ' single quotes, so that it can look up through $templateCache for getting the template.
<ng-include src="'commontemplates/productView/shoes'"></ng-include>

Vue.js block repeat table rows doesn't work in IE

I would like to repeat adding table rows using a template tag with vue.js, but it doesn't work in IE11. Here is the code.
<table border="1">
<tr>
<td rowspan="2">ID</td>
<td colspan="2">Name</td>
</tr>
<tr>
<td>Height</td>
<td>Weight</td>
</tr>
<template v-repeat="items">
<tr>
<td rowspan="2">{{id}}</td>
<td colspan="2">{{name}}</td>
</tr>
<tr>
<td>{{height}}</td>
<td>{{weight}}</td>
</tr>
</template>
</table>
Any help?
See http://vuejs.org/guide/components.html#Using_Components and the warning at the end of that section:
The table element has restrictions on what elements can appear inside
it, so custom elements will be hoisted out and not render properly. In
those cases you can use the component directive syntax:
<tr v-component="my-component"></tr>.
I found a solution that changed the <template> tag to a <tbody> tag. However there would be multiple <tbody> tags in a table, I hope this is the best solution in this case.
Make a long story short, This is HTML restrictions in IE, if you want compatibility, you will have to change your HTML structure.
I found an issue with similar question like yours here: https://github.com/vuejs/vue/issues/2404
Vue renders the template into real html before compiling it, so the same html restrictions apply for Vue templates, no matter how you define it.
IE does not support inside elements like , ..

AngularJS - Directives with Angular UI Bootstrap

I'm using Angular UI - Bootstrap, specifically the Typeahead directive. http://angular-ui.github.io/bootstrap/#/typeahead
I'm attempting to use the 'typeahead-template-url' to create custom html templates for my suggestion boxes. After trying multiple techniques, unsuccessfully, I discovered that by purposely messing up my quotation marks 'solved' the display issues. I would love to understand why this is breaking and get it working properly.
For example: this works
<table class="> <!--see class quote error -->
<tr>
<td>
<div ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)">
<a>ID{{ match.model.id }} - {{ match.model.text }}</a>
</div>
</td>
</tr>
</table>
This DOESN'T WORK
<table class="">
<tr>
<td>
<div ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)">
<a>ID{{ match.model.id }} - {{ match.model.text }}</a>
</div>
</td>
</tr>
</table>
FIDDLE is here: http://jsfiddle.net/nicktest222/JXtaZ/24/
Additionally, when you select an item in the results list, it returns the entire object. How can I get it to return a specific property in the object?
Any help would be greatly appreciated.
Thanks
I think it is the way you add your template (columnTwo.html) in JSFiddle.
Look at my demo (which is based on yours): http://jsbin.com/aMOrOra/1/edit?html,js,output
As for the typeahead property:
<input type="text" ng-model="monkey" typeahead-template-url="columnTwo.html" typeahead="suggestion as suggestion.text for suggestion in sample_data | filter: $viewValue" />
Here it means that the suggestion object is used as the selected value, but I want to display only the suggestion.text property in the box. But monkey will still be set to the selected suggestion object.
Just so you know, your current filter will look for the query on every properties of the suggestion object, not only text.
EDIT: To filter only the text property, use the filter like this:
filter:{'text':$viewValue}

knockout html binding with another binding inside

I'm using knockout to dynamically loading content into parts of the page, using the HTML binding.
the problem is that the html I want to bind has to do call a function onclick and I need the information about the target and the data that knockout easily send.
something like this:
myFunction($parent, $data)
HTML:
<table>
<tbody data-bind="foreach: rows" >
<tr>
<td data-bind="html: rowValue">this will be a link</td>
</tr>
</tbody>
</table>
Later I set the value to be a link with a knockout binding inside:
rowValue("<a href='#' data-bind=click:alert('hello')" + result.Data + "</a>");
Please check the fiddle here to see the full working code.
You can see the difference between the 2 lines I wrote, if I do a javascript onclick it works, but obviously ko is missing a late binding.
I've seen many questions about this but can't find one with a definitive answer.
I want to do this with KO, how can this be accomplished?
with templates maybe?
KO applies bindings when you call ko.applyBindings.
So if you modify the dom after applyBindings has been called. KO won't be aware of the new dom element.
You can use template this way :
<table>
<tbody data-bind="foreach: sitesTable.rows" >
<tr data-bind="foreach: row">
<td data-bind="template: 'myTemplate' "></td>
</tr>
</tbody>
</table>
<br/>
click here
<script id="myTemplate" type="text/html">
click
</script>
edit by Maurizio. Use this fiddle as the other linkseems to be broken:
See fiddle

Categories