I am making DOM object through javascript and i want it to render it through angularjs but it display like [object HTMLDivElement]
but in browser console its
but it renders like
.directive('attachmentify', [
function() {
return {
restrict: 'A',
scope: {
item: "#filename"
},
template: "<div ng-bind-html='content'></div>",
compile: function(iElement, iAttrs) {
return function($scope, element, attr) {
var file = $scope.item;
// console.log
// $scope.file =file;
}
},
controller: function($scope) {
var img = ['jpg', 'jpeg', 'png'];
var c = 0;
img.forEach(function(element, index) {
if ($scope.item.endsWith(element)) c++;
});
if (c) {
var div = document.createElement('div');
div.setAttribute('name', 'samundra')
div.innerHTML = "ram"
} else {
var div = document.createElement('div');
div.setAttribute('name', 'ramundra')
div.innerHTML = "sam"
}
$scope.content = div;
console.log(div);
}
}
}
])
In your controller instead of assign DOM element instance, You can set $scope.content to html
$scope.content="<div name='ramundra'>ram></div>";
Related
I've gotten this menu to work without filtering it, but now I'm doing an ajax request to filter out menu items the user isn't supposed to see, and I'm having some trouble to figure out how to set the resulting menu data, the line that is not working is commented below:
<script>
import { ref } from 'vue';
import axios from 'axios';
var currentSelected = 'device_access';
var menuData = [
{
text: 'Device Access',
id: 'device_access',
children: [
{
text: 'Interactive',
link: '/connection_center'
},{
text: 'Reservation',
link: '/reserve_probe'
}, {
text: 'Reservation Vue',
link: '/reservation.html'
}
]
}, {
text: 'Automation',
id: 'automation',
show: ['is_mxadmin', 'can_schedule_scripts'],
children: [
{
text: 'Builder',
link: '/builder',
},{
text: 'Execution Results',
link: '/test_suite_execution_results'
},
]
}
];
function hasMatch(props, list) {
var match = false;
for (var i=0; i < list.length && !match; i++) {
match = props[list[i]];
}
return match;
}
export default {
name: 'Header',
setup() {
const cursorPosition = ref('0px');
const cursorWidth = ref('0px');
const cursorVisible = ref('visible');
//the menu is zero length until I get the data:
const menu = ref([]);
return {
menu,
cursorPosition,
cursorWidth,
cursorVisible
}
},
created() {
let that = this;
axios.get('navigation_props')
.then(function(res) {
var data = res.data;
var result = [];
menuData.forEach(function(item) {
if (!item.show || hasMatch(data, item.show)) {
var children = [];
item.children.forEach(function (child) {
if (!child.show || hasMatch(data, child.show)) {
children.push({ text: child.text, link: child.link });
}
});
if (children.length > 0) {
result.push({ text: item.text,
children: children, lengthClass: "length_" + children.length });
}
}
});
//continues after comment
this is probably the only thing wrong, I've run this in the debugger and I'm getting the
correct data:
that.$refs.menu = result;
since the menu is not being rebuilt, then this fails:
//this.restoreCursor();
})
.catch(error => {
console.log(error)
// Manage errors if found any
});
},
this.$refs is for template refs, which are not the same as the refs from setup().
And the data fetching in created() should probably be moved to onMounted() in setup(), where the axios.get() callback sets menu.value with the results:
import { onMounted, ref } from 'vue'
export default {
setup() {
const menu = ref([])
onMounted(() => {
axios.get(/*...*/).then(res => {
const results = /* massage res.data */
menu.value = results
})
})
return {
menu
}
}
}
I finally figured out the problem.
This code above will probably work with:
that.menu = result;
You don't need: that.$refs.menu
You can't do it in setup because for some reason "that" is not yet defined.
In my working code I added a new method:
methods: {
setMenuData: function() {
this.menu = filterMenu();
},
}
And "this" is properly defined inside them.
Assume I have a SAPUI5 application like this sample application.
As it can be seen in the code of this application, the views are somehow split into several blocks and attached to main view like this:
<ObjectPageSubSection title="Payment information">
<blocks>
<personal:PersonalBlockPart1 id="part1"/>
</blocks>
<moreBlocks>
<personal:PersonalBlockPart2 id="part2"/>
</moreBlocks>
</ObjectPageSubSection>
And the PersonalBlockPart1 has been split into two files like this:
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns:core="sap.ui.core" xmlns:forms="sap.ui.layout.form" xmlns="sap.m">
<forms:SimpleForm editable="false" layout="ColumnLayout">
<core:Title text="Main Payment Method"/>
<Label text="Bank Transfer"/>
<Text text="Sparkasse Heimfeld, Germany"/>
</forms:SimpleForm>
</mvc:View>
sap.ui.define(['sap/uxap/BlockBase'], function (BlockBase) {
"use strict";
var BlockJobInfoPart1 = BlockBase.extend("sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1", {
metadata: {
views: {
Collapsed: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
},
Expanded: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
}
}
}
});
return BlockJobInfoPart1;
});
If I want to set fieldGroupIds a direct way is to do it in xml fragment of the code! for example:
<Text text="Sparkasse Heimfeld, Germany" fieldGroupIds="XYZ1"/>
My question is how can I do it in the parent view, something like this:
<blocks>
<personal:PersonalBlockPart1 id="part1" fieldGroupIds="XYZ1"/>
</blocks>
<moreBlocks>
<personal:PersonalBlockPart2 id="part2" fieldGroupIds="XYZ2"/>
</moreBlocks>
I tried it, and obviously it does not apply to children controls. However, I think there could be a solution that read this property from main XML view and apply it in the JS file on all the enclosing controls, something like this:
sap.ui.define(['sap/uxap/BlockBase'], function (BlockBase) {
"use strict";
var BlockJobInfoPart1 = BlockBase.extend("sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1", {
metadata: {
views: {
Collapsed: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
},
Expanded: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
}
}
},
onViewInit: function(){
// pseudocode
var sFieldGroupIds = this.getFieldGroupIds();
var aControls = this.getAllFeidls();
iterate over aControls and set the sFieldGroupId
}
});
return BlockJobInfoPart1;
});
I must use the onBeforeRendering function:
sap.ui.define(['sap/uxap/BlockBase'], function (BlockBase) {
"use strict";
var setFieldGroupIdsRecursively = function (oControl, sFieldGroupIds) {
var aPossibleAggregations = ["items", "content", "form", "formContainers", "formElements", "fields", "cells"];
if (oControl instanceof sap.m.InputBase || oControl instanceof sap.ui.comp.smartfield.SmartField) {
oControl.setFieldGroupIds(sFieldGroupIds);
return;
}
for (var i = 0; i < aPossibleAggregations.length; i += 1) {
var aControlAggregation = oControl.getAggregation(aPossibleAggregations[i]);
if (aControlAggregation) {
// generally, aggregations are of type Array
if (aControlAggregation instanceof Array) {
for (var j = 0; j < aControlAggregation.length; j += 1) {
setFieldGroupIdsRecursively(aControlAggregation[j], sFieldGroupIds);
}
}
else { // ...however, with sap.ui.layout.form.Form, it is a single object *sigh*
setFieldGroupIdsRecursively(aControlAggregation, sFieldGroupIds);
}
}
}
};
var BlockJobInfoPart1 = BlockBase.extend("sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1", {
metadata: {
views: {
Collapsed: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
},
Expanded: {
viewName: "sap.uxap.sample.SharedBlocks.employment.BlockJobInfoPart1",
type: "XML"
}
}
},
onBeforeRendering: function () {
var aFieldGroupIds = this.getFieldGroupIds(),
sFieldGroupIds = "";
if (aFieldGroupIds.length > 0) {
sFieldGroupIds = aFieldGroupIds.join();
var oView = sap.ui.getCore().byId(this.getSelectedView());
if (oView) {
var aContent = oView.getContent();
for (var j = 0; j < aContent.length; j++) {
setFieldGroupIdsRecursively(aContent[j], sFieldGroupIds);
}
}
}
}
});
return BlockJobInfoPart1;
});
My database return a field with raw html string. I'd like to modify element by adding ng-click='showImage()'. For example, the original html is:
<p>
<img src="http://mywebsite.com/img-1.jpg" />
</p>
My source code in my controller:
var parser = new DOMParser();
var doc = parser.parseFromString($scope.body, 'text/html');
var images = doc.getElementsByTagName('img')
for (var i = 0; i < images.length; i++ ) {
var img = images[i];
img.setAttribute('ng-click','showImage()');
$scope.addImage(img.getAttribute('src'));
}
$scope.body = doc.documentElement.innerHTML;
The result is correct:
<p>
<img src="http://mywebsite.com/img-1.jpg" ng-click="showImage()"/>
</p>
But I got the following error message when I click the image:
Uncaught TypeError: scope.$apply is not a function
Why? Can anybody help? Thanks.
Edit (complete source code for the controller):
(function() {
'use strict';
angular
.module('App')
.controller('DetailsController', DetailsController);
DetailsController.$inject = ['$scope','$stateParams','ParseSvc','$controller'];
function DetailsController($scope, $stateParams, ParseSvc, $controller) {
$controller('BaseController', { $scope: $scope });
$scope.article = JSON.parse($stateParams.article);
activate();
function activate() {
var parser = new DOMParser();
var doc = parser.parseFromString($scope.article.body, 'text/html');
var images = doc.getElementsByTagName('img')
for (var i = 0; i < images.length; i++ ) {
var img = images[i];
img.setAttribute('ng-click','showImages(' + i + ')');
$scope.addImage(img.getAttribute('src'));
}
$scope.article.body = doc.documentElement.innerHTML;
}
}
})();
Base controller:
(function() {
'use strict';
angular.module('App')
.controller('BaseController', ['$scope','$ionicModal','$ionicSlideBoxDelegate','$ionicScrollDelegate',
function($scope, $ionicModal, $ionicSlideBoxDelegate, $ionicScrollDelegate) {
$scope.allImages = [];
$scope.zoomMin = 1;
$scope.addImage = function(src) {
$scope.allImages.push({'src' : src});
}
$scope.showImages = function(index) {
$scope.activeSlide = index;
$scope.showModal('templates/gallery-zoomview.html');
}
$scope.showModal = function(templateUrl) {
$ionicModal.fromTemplateUrl(templateUrl, {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
$scope.modal.show();
});
};
// Close the modal
$scope.closeModal = function() {
$scope.modal.hide();
$scope.modal.remove();
};
$scope.updateSlideStatus = function(slide) {
var zoomFactor = $ionicScrollDelegate.$getByHandle('scrollHandle' + slide).getScrollPosition().zoom;
if (zoomFactor == $scope.zoomMin) {
$ionicSlideBoxDelegate.enableSlide(true);
} else {
$ionicSlideBoxDelegate.enableSlide(false);
}
}
}]);
})();
I built jQuery Masonry layout with infinite scroll and filtering.
My problem is that when a filter clicked before scrolling, the content loaded with infinite scroll is not filtered.
Is there any way to fix it?
Here is the link to check: http://www.jcvergara.com/working/
Here is the full masonry code:
$(document).ready(function(){
var $container = $('.container');
// initialize
$container.masonry({
columnWidth: 250,
itemSelector: '.item',
isFitWidth: true
});
$container.masonry( 'on', 'layoutComplete', function() {
$('.right-line').css('height', $('.container').height());
});
$('.right-line').css('height', $('.container').height());
// infinite scroll
var $container = $('#content');
$container.infinitescroll({
navSelector : "nav.posts-navigation",
nextSelector : "div.nav-previous a:first",
itemSelector : "#content div.item",
},
// trigger Masonry as a callback
function( newElements ) {
var $newElems = $( newElements );
$container.masonry( 'appended', $newElems );
// open posts in ajax
$('.post-link').click(function(){
$('.openarticle').css('display', 'block');
var post_link = $(this).attr('href');
$('#openthis').html('<div class="title"><h2>Loading..</h2><div class="text"></div>');
$('#openthis').load(post_link);
$('<a></a>', {
text: 'Close',
class: 'close',
id: 'close',
href: '#'
})
.prependTo($('.openarticle .main'))
.click(function() {
$('.openarticle').css('display', 'none');
$('#close').remove();
});
return false;
});
}
);
// filtering
$(".cat-item a").click(function(e) {
e.preventDefault();
var cut_url = "http://www.jcvergara.com/category/";
var group = $(this).attr('href');
group = group.replace(cut_url, '').slice(0,-1);
var group_class = "." + group;
$(".cat-item a.active").removeClass('active');
$(this).addClass('active');
if(group != "all") {
$(".item").hide();
$(group_class).show();
$container.masonry();
} else {
$(".item").show();
$container.masonry();
}
});
});
Try using "on" for your click function:
// filtering
$(".cat-item a").on( "click",function (e) {
e.preventDefault();
var cut_url = "http://www.jcvergara.com/category/";
var group = $(this).attr('href');
group = group.replace(cut_url, '').slice(0,-1);
var group_class = "." + group;
$(".cat-item a.active").removeClass('active');
$(this).addClass('active');
if(group != "all") {
$(".item").hide();
$(group_class).show();
$container.masonry();
} else {
$(".item").show();
$container.masonry();
}
});
Firebug is giving me no error messages, but it's not working. The idea is regardless of whether the user picks an option from dropdown or if they type in something in search box, I want the alert() message defined below to alert what the value of the variable result is (e.g. {filter: Germany}). And it doesn't. I think the javascript breaks down right when a new Form instance is instantiated because I tried putting an alert in the Form variable and it was never triggered. Note that everything that pertains to this issue occurs when form.calculation() is called.
markup:
<fieldset>
<select name="filter" alter-data="dropFilter">
<option>Germany</option>
<option>Ukraine</option>
<option>Estonia</option>
</select>
<input type="text" alter-data="searchFilter" />
</fieldset>
javascript (below the body tag)
<script>
(function($){
var listview = $('#listview');
var lists = (function(){
var criteria = {
dropFilter: {
insert: function(value){
if(value)
return handleFilter("filter", value);
},
msg: "Filtering..."
},
searchFilter: {
insert: function(value){
if(value)
return handleFilter("search", value);
},
msg: "Searching..."
}
}
var handleFilter = function(key,value){
return {key: value};
}
return {
create: function(component){
var component = component.href.substring(component.href.lastIndexOf('#') + 1);
return component;
},
setDefaults: function(component){
var parameter = {};
switch(component){
case "sites":
parameter = {
'order': 'site_num',
'per_page': '20',
'url': 'sites'
}
}
return parameter;
},
getCriteria: function(criterion){
return criteria[criterion];
},
addCriteria: function(criterion, method){
criteria[criterion] = method;
}
}
})();
var Form = function(form){
var fields = [];
$(form[0].elements).each(function(){
var field = $(this);
if(typeof field.attr('alter-data') !== 'undefined') fields.push(new Field(field));
})
}
Form.prototype = {
initiate: function(){
for(field in this.fields){
this.fields[field].calculate();
}
},
isCalculable: function(){
for(field in this.fields){
if(!this.fields[field].alterData){
return false;
}
}
return true;
}
}
var Field = function(field){
this.field = field;
this.alterData = false;
this.attach("change");
this.attach("keyup");
}
Field.prototype = {
attach: function(event){
var obj = this;
if(event == "change"){
obj.field.bind("change", function(){
return obj.calculate();
})
}
if(event == "keyup"){
obj.field.bind("keyup", function(e){
return obj.calculate();
})
}
},
calculate: function(){
var obj = this,
field = obj.field,
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = field.attr("alter-data").split(" "),
container = field.parent(),
messages = [];
field.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
if(field.val()){
var result = criterion.insert(field.val());
container.addClass("waitingMsg");
messages.push(criterion.msg);
obj.alterData = true;
alert(result);
initializeTable(result);
}
else {
return false;
obj.alterData = false;
}
}
if(messages.length){
for(msg in messages){
msgList.append("<li>" + messages[msg] + "</li");
}
}
else{
msgList.remove();
}
}
}
$('#dashboard a').click(function(){
var currentComponent = lists.create(this);
var custom = lists.setDefaults(currentComponent);
initializeTable(custom);
});
var initializeTable = function(custom){
var defaults = {};
var custom = custom || {};
var query_string = $.extend(defaults, custom);
var params = [];
$.each(query_string, function(key,value){
params += key + ': ' + value;
})
var url = custom['url'];
$.ajax({
type: 'GET',
url: '/' + url,
data: params,
dataType: 'html',
error: function(){},
beforeSend: function(){},
complete: function() {},
success: function(response) {
listview.html(response);
}
})
}
$.extend($.fn, {
calculation: function(){
var formReady = new Form($(this));
if(formReady.isCalculable) {
formReady.initiate();
}
}
})
var form = $('fieldset');
form.calculation();
})(jQuery)
Thank you for anyone who responds. I spent a lot of time trying to make this work.
The initial problem as to why the alert() was not being triggered when Form is instantiated is because, as you can see, the elements property belongs to the Form object, not fieldset object. And as you can see in the html, I place the fields as descendents of the fieldset object, not form.