AngularJS ng-click not invoked where dom inside repeat - angularjs

When the ng-repeat area in my code example is executed the ng-click actions are not working. Although if moved outside the ng-repeat it would work. Which am not sure how to solve or what is causing this to happen,
my HTML
<table class="table table-bordered table-hover" id="my-vehicles-table" ng-controller="VehicleController">
<tbody>
<tr ng-repeat="car in cars">
<td>{% ng car._get_model_display.make_display %} {% ng car._get_model_display.model_display %} {% ng car._get_model_display.trim_display %}</td>
<td>{% ng car.created_since %}</td>
<td>{% ng car.view_count %}</td>
<td>
{% trans 'Delete' %}
{% trans 'Edit' %}
</td>
</tr>
</tbody>
</table>
where by {% ng xxx %} will output {{ xx }} this is the django template tag for it. The content is rendered normally, even inside the anchor for delete, I can see delete($event, num) so its populating the values correctly.
But when I click the delete anchor its not invoking the function delete from my following controller
'use strict';
function VehicleController($scope, car) {
car.query(
// params
{created_by: '1'},
// success
function(data) {
$scope.cars = data.objects;
},
// error
function(data) {
}
);
var init = function() {
};
$scope.delete = function($event) {
console.log('dude');
// car.delete({id: id});
}
// initialize values
init();
}

delete($event, {% ng car.id %}) should probably just be delete($event, car.id)
I'm presuming {% ng %} is custom {{ }}? I've not seen that before. Either way, you don't need the {{ or {% ng inside of the ng-click="", as that's $eval'ed.

Related

CKAN - adding custom fields with ckenxt-scheming

i'm working with ckanext-scheming and trying to add a custom field similar to repeating subfields with few modifications (below are few files that define the field and it's behavior), for the most part it works correct but it doesn't get submitted to the database (although once i intercept the package create action, i can see the field data is there), any ideas are welcomed:
the scheming yaml part:
- field_name: tag_string
label: Tags
form_snippet: custom_tags.html
display_snippet: modified_repeating_subfields.html
help_text: >-
Additional keywords useful for ...
the form snippet:
{% import 'macros/form.html' as form %}
{% asset 'ckanext-dalrrdemcdcpr/facets-active-js' %}
{%
set options=[
{'value': '001', 'text': _('Discipline')}
, {'value': '002', 'text': _('Place')}
, {'value': '003', 'text': _('Stratum')}
, {'value': "004", "text":_("Temporal")}
, {'value': "005", "text":_("Theme")}
]
%}
{%- set extra_html = caller() if caller -%}
{% set classes = (classes|list) %}
{% call form.input_block(field.field_name, field.label, "", classes, extra_html=extra_html, is_required=false) %}
<div class="repeating_custom_tag_row-index-0" id="repeating_custom_tag_row-index-0" data-module="repeating_tags_handler">
<div class="metadata_tags_holder">
<div class="metadata_tags_styler">
<div class="metadata_tags_input">
<label for="custom_delete" class="input-group-text">{{ _('Input tag') }}</label>
<input class="form-control" id="repeating_custom_tag_row-index0-tag-input-index-0" type="text" name="repeating_custom_tag_row-index0-tag-input-index-0" value="" placeholder=""/>
</div>
<div class="metadata_tags_type_select">
<div><label for="tag_select" class="input-group-text">{{_('Input tag type')}}</label></div>
<select id="tag_select" name="repeating_custom_tag_row-index0-select-input-index-0" required>
{% for option in options %}
<option value="{{ option.value }}"{% if option.value == selected %} selected{% endif %}>{{ option.text or option.value }}</option>
{% endfor %}
</select>
</div>
<div class="tags_buttons_wrapper">
<div class="tags_handling_buttons">
<button class="btn btn-success add_metadata_tags_btn">Add</button>
<button class="btn btn-danger remove_metadata_tags_btn"><i class="fa fa-trash"></i>Remove</button>
</div>
</div>
</div>
</div>
</div>
{% endcall %}
the display snippet (don't think it's useful):
{% set fields = data[field.field_name] %}
{% block subfield_display %}
{% for field_data in fields %}
<div class="panel panel-default">
<div class="panel-body">
<dl class="scheming-subfield-list">
{% for subfield in field.repeating_subfields %}
<dt class="dataset-label">
{{ h.scheming_language_text(subfield.label) }}
</dt>
<dd>
{%- snippet 'scheming/snippets/display_field.html',
field=subfield,
data=field_data,
entity_type=entity_type,
object_type=object_type
-%}
</dd>
{% endfor %}
</dl>
</div>
</div>
{% endfor %}
{% endblock %}
this is how the relevant part of the form looks (the tags):
the js module controlling tags fields behavior:
ckan.module("repeating_tags_handler", function ($){
/*
control muliple interaction regarding the tags
section, handles both css and buttons behavior.
*/
return {
initialize: function(){
$.proxyAll(this,/_on/);
// set the styles before copying the section
let add_btns = $(".add_metadata_tags_btn")
add_btns.each((idx,add_btn) => {add_btn.style.marginRight="2px"})
$(document).on('click','.add_metadata_tags_btn',this._on_add_tags)
$(document).on('click','.remove_metadata_tags_btn',this._on_remove_tags)
let repeating_fields_wrapper = $(".repeating_custom_tag_row-index-0")
repeating_fields_wrapper.css({"margin-bottom":"30px"})
let tags_holder = $(".metadata_tags_holder")
tags_holder.css("width:100%")
$(".metadata_tags_styler").css({"width":"100%", "display": 'flex', 'flex-direction': 'row'})
$(".metadata_tags_input").css({"width":"40%"})
$(".metadata_tags_type_select").css({"width":"30%"})//tag_select
$("#tag_select").css({"width":"100%", "height":"34px", "margin-left":"4px"})
$(".tags_buttons_wrapper").css({"margin-left": "4px", "padding-top": "2px"})
$(".tags_handling_buttons").css({"width":"100%","padding-top":"22px", "display": "flex", "flex-direction": "row", "margin-left":"4px"})
this.section_html = tags_holder.html()
const config = { attributes: true, childList: true, subtree: true };
//const added_items_observer = new MutationObserver(this.added_items_mutation_observer);
//added_items_observer.observe(repeating_fields_wrapper.get(0), config)
},
_on_add_tags:function(e){
e.preventDefault()
//let search_parent = e.target.parentElement.parentElement.parentElement.parentElement
let search_parent = e.target.closest(".metadata_tags_styler")
let new_index = Array.from(search_parent.parentNode.children).indexOf(search_parent) +1
let new_index_text = `index-${new_index}`
this.section_html = this.section_html.replace(/index-[0-9]/g, new_index_text)
this.el.append(this.section_html)
},
_on_remove_tags:function(e){
e.preventDefault()
let removed_tag_row = e.target.closest(".metadata_tags_styler")
//let removed_tag_row = e.target.parentElement.parentElement.parentElement.parentElement
removed_tag_row.remove()
},
}
})
and finally this is a Runtime error screenshot i raised for you - dear - to see the tags data is there:
thank you!

data from component to view (Angularjs)

I am sure this is something simple, but I cannot seem to pass information from a component to a view. I search for this on stackoverflow and google but could not find a solution.
Here is the javascript component call to the API, which prints the information to the console,
component.js
$ctrl.getInformation = function() {
// call php controller.
// return audits for html file.
$http.get(`path/to/getInformation/${$ctrl.path.idTo}`).then(function(responseState) {
console.log('sucessfull callback from server', responseState.data);
return responseState.data;
});
}
View template.html file:
<tr ng-repeat="i in vm.getInformation">
<td> {{ vm.getInformation().data[i].Date }}</td>
<td> {{ vm.getInformation(responseState.data[i].Date) }} </td>
</tr>
Can anyone show me why is it not rendering the information from the component to the template file?
You need to assign your fetched data to a $scope variable or a variable in the controller then you can loop it. In your controller you need to change your code to
$ctrl.information = [];
$ctrl.getInformation = function() {
$http.get(`path/to/getInformation/${$ctrl.path.idTo}`).then(function(responseState) {
console.log('sucessfull callback from server', responseState.data);
$ctrl.information = responseState.data;
});
}
Then in your html
<tr ng-repeat="data in vm.information">
<td> {{ data.Date }}</td>
<td> {{ data.whatever) }} </td>
</tr>

Angularjs filling a table

I am not able to enter a list in a table within the html of the body. This list came using Angularjs, ajax request with django. The incoming list contains other lists within it, which can vary in size every query. Example: [["a","b","c"],["a","b","c"],["a","b","c"]] or [["a","b","c","d","e"],["a","b","c","d","e"],["a","b","c","d","e"]]
File dfp_consulta.js
function ListDropdown($scope, $http) {
$scope.bvmf = {ccvms : [ '1023', '10456', '10472'],
consolidados : [ 't', 'f' ],
origens : [ 'ITR', 'DFP' ],
balancos : [ '1', '2', '3', '4'],
periodos : [ '1-3', '1-6', '1-9', '1-12' ],
anos : [ '1997', '1998', '1999', '2012' ]
$scope.range=[]
$scope.send=function(ccvm, consolidado, origem, balanco, periodo, ano, ano_doc){
$http({
method:'POST',
url:'/sending/',
data:ccvm+consolidado+origem+balanco+periodo+ano+ano_doc,
headers:{'Content-Type': 'application/x-www-form-urlencoded'},
}).success(function(c){
$scope.range=c
})
}
}
File dfp_consulta.html
{% extends "base.html" %}
{% block corpo %}
<div ng-app="" ng-controller="ListDropdown">
<select ng-model="ccvm" ng-options="ccvm as ccvm for ccvm in bvmf.ccvms"></select><br>
<select ng-model="consolidado" ng-disabled="!ccvm" ng-options="consolidado for consolidado in bvmf.consolidados" ></select><br>
<select ng-model="origem" ng-disabled="!consolidado" ng-options="origem for origem in bvmf.origens" ></select><br>
<select ng-model="balanco" ng-disabled="!origem" ng-options="balanco for balanco in bvmf.balancos" ></select><br>
<select ng-model="periodo" ng-disabled="!balanco" ng-options="periodo for periodo in bvmf.periodos" ></select><br>
<select ng-model="ano" ng-disabled="!periodo" ng-options="ano for ano in bvmf.anos" ></select><br>
<select ng-model="ano_doc" ng-disabled="!ano" ng-options="ano_doc for ano_doc in bvmf.anos" ng-change="send(ccvm,consolidado,origem,balanco,periodo,ano,ano_doc)"></select><br>
<table class='table table-hover'>
{% for i in range %}
<tr>
{% for s in i %}
<td>{{ s }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
I am getting in $scope.range for example, the following list [["a", "b", "c"] ["a", "b", "c"] ["a", "b "," c "]], however, {% for i in range %} is not using the range array
The problem is that both Django and AngularJS share the same syntax of Jinja2 for variable substitution in templates.
The easiest option would be to tell Django not to use it's syntax in places you need to use angularjs variable substitution - in other words, use verbatim tag:
{% block corpo %}
{% verbatim %}
<div ng-app="" ng-controller="ListDropdown">
<select ng-model="ccvm" ng-options="ccvm as ccvm for ccvm in bvmf.ccvms"></select><br>
<select ng-model="consolidado" ng-disabled="!ccvm" ng-options="consolidado for consolidado in bvmf.consolidados" ></select><br>
<select ng-model="origem" ng-disabled="!consolidado" ng-options="origem for origem in bvmf.origens" ></select><br>
<select ng-model="balanco" ng-disabled="!origem" ng-options="balanco for balanco in bvmf.balancos" ></select><br>
<select ng-model="periodo" ng-disabled="!balanco" ng-options="periodo for periodo in bvmf.periodos" ></select><br>
<select ng-model="ano" ng-disabled="!periodo" ng-options="ano for ano in bvmf.anos" ></select><br>
<select ng-model="ano_doc" ng-disabled="!ano" ng-options="ano_doc for ano_doc in bvmf.anos" ng-change="send(ccvm,consolidado,origem,balanco,periodo,ano,ano_doc)"></select><br>
<table>
<tr ng-model="item2" ng-repeat="item2 in range">
<td ng-repeat="item3 in item2">{{ item3 }}</td>
</tr>
</table>
</div>
{% endverbatim %}
{% endblock %}
The new table structure allows the build with angularjs amounts different of row and column <tr ng-repeat> and <td ng-repeat>
See also:
Integrate AngularJS with Django
Stackoverflow - Django not working with Angularjs

ng-repeat value is not visible inside nested tag

I am new to angularjs and trying to work with ng-repeat but somehow ng-repeat's key/value is not visible if I am trying to print it in nested tags
working:
<div>
<table>
<tr ng-repeat="prop in array">
<td><span ng-bind-html="prop.field1"></span></td>
</tr>
</table>
</div>
And below code is not working:-
<div ng-repeat="prop in array">
<table>
<tr>
<td><span ng-bind-html="prop.field1"></span></td>
</tr>
</table>
</div>
Updated:
var $app = angular.module('apps', ['ngSanitize']);
$app.controller('cntr', ['$scope', function($scope) {
$scope.guestList = [{
dob: '12/12/12'
}];
}]);
For html to show properly in angular js you have to 'sanitize' it, using the $sce provider from AngularJS. Read here: https://docs.angularjs.org/api/ng/service/$sce
In principle, before you bind your variable to html output, you have to sanitize it like this:
$scope.guest.sanitizedInput = $sce.trustAsHtml($scope.guest.res_addr1);
and html:
<td class="table-column-value res-addr1-value"><span ng-bind-html="guest.sanitizedInput"></span>

Nested Angular directives not working as expected

I have been making a directive to display some HTML and handle events as it seemed sensible to keep this code reusable. This directive was placed inside a ng-repeat and worked as expected.
Now I come to add some more display logic to it: 2 modes 'grid' and 'list', and create 2 ng-repeat elements for each mode. At this point the whole thing seems to fall apart with rendering doing some unexpected stuff.
I have created a Plunkr to demonstrate: http://plnkr.co/edit/GjxOjxE7KOlvYjxCqVJj?p=preview
App.js
var app = angular.module('myApp', []);
app.directive('documentObject', [function() {
return {
restrict: 'E',
transclude: true,
scope: {
object: '=',
viewmode: '=',
},
templateUrl: 'storage-object.html',
link: function(scope, element, attrs) {
if (scope.viewMode === 'grid') {
scope.class = 'grid-view';
} else {
scope.class = 'list-view';
}
}
}
}]);
app.controller('DocumentsController', ['$scope', function($scope) {
$scope.browser = {
viewMode: 'grid',
files: [{name: 'First'}, {name: 'Second'}, {name: 'Third'}]
};
}]);
index.html
<div ng-switch="browser.viewMode" class="filebrowser">
<div ng-switch-when="grid">
<div ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</div>
</div>
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<document-object viewmode="browser.viewMode" object="file"></document-object>
</tr>
</table>
</div>
storage-object.html
<div ng-if="viewmode == 'grid'" class="filebrowser {{ viewmode }}">
Grid Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
<td ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</td>
Grid mode should only display the items as a grid, and list mode as a table. What is happening is grid mode is displaying everything and list mode is just rendering one element.
What is going on here?
This happens because you are not allowed to have anything else as a direct child of a <tr> than a <td> or <th> element.
In your case you are having a <document-object> element, which causes the browser to move it around (as it is not allowed to be where it is), which in turn confuses ng-switch.
Wrapping <document-object> in <td></td> and chenging it's template (e.g. replacing <td> with <div>), solves the problem.
index.html:
...
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td>
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>
storage-object.html:
...
<div ng-if="viewmode == 'list'" class="filebrowser {{ viewmode }}">
List Mode: {{ viewmode }}
<span class="file-label {{ class }}">{{ object.name }}</span>
</div>
See, also, this updated plunkr.
Please see here http://plnkr.co/edit/aMOsKAATd4aBl0swPik1?p=preview
you missed <td> tag
<table ng-switch-when="list">
<tr ng-repeat="file in browser.files">
<td> <!--here -->
<document-object viewmode="browser.viewMode" object="file"></document-object>
</td>
</tr>
</table>

Resources