How to dynamic add new element in Angularjs - json

I have a ng-repeat to loop my object value to view.
Then I want to have a button to add new blank element to the last of ng-repeat value.
How can I do this in angular?
My data is json object. I tried
In controller
$scope.objs = {'a': 'a', 'b':'b'};
In view
{{Object.keys(objs).length}};
But nothing show in view.
Update
<div ng-repeat="docstep in docs.docsteps" class="docstep">
{{docstep.text}}
</div>
Then I want to get the length of objects so I can .length + 1 in the button click
But I have no idea how to get objects length. Or is there any better idea?

Bind a click handler to the button using ng-click:
<div ng-repeat="docstep in docs.docsteps" class="docstep">
<input type="text" value="{{docstep.text}}">
</div>
<button ng-click="addNew()">Add another input</button>
When this button is clicked. It will add another blank input
<br>Which the new input will be docstep3
This is how your JS should look:
var myApp = angular.module('myApp',[]);
myApp.run(function($rootScope){
$rootScope.docs = {
"docsteps" : {
"docstep1" : {
"text" : "a"
},
"docstep2" : {
"text" : "b"
}
}
}
var c = 2;
$rootScope.addNew = function(){
count++;
$rootScope.docs.docsteps["docstep"+count] = {"text":count}
}
});
NOTE: You should use ng-app to define work area for angular and use controllers to reside the models(docs) and define the behaviour of your view (addNew).

I took your ng-repeat and made it work. Notice I put your object in the $rootScope but you can apply the same object to any scope that your ng-repeat is in.
JS
var myApp = angular.module('myApp',[]);
myApp.run(function($rootScope){
$rootScope.docs={docsteps:[{text:'A'},{text:'B'},{text:'C'}]};
});
JSFIDDLE: http://jsfiddle.net/mac1175/Snn9p/

Related

HTML website url contains /#[object Object] when navigating

I have a website and it contains the following code:
<li class="scroll-to-section">Services</li>
and the appropriate section:
<section class="section" id="services">
...
</section>
When I press the li element, the page scrolls to the services section as expected however, the url is appended with /#[object Object] instead of /services.
Here's an image:
Any idea about what the issue may be?
EDIT: Sorry, forgot to add the javascript: The issue was the new_target variable. I had to change it to new_target as it was also target before and that fixed the issue!
$(document).ready(function() {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on("click", function(e) {
e.preventDefault();
$(document).off("scroll");
$("a").each(function() {
$(this).removeClass("active");
});
$(this).addClass("active");
var target = this.hash,
menu = target;
var new_target = $(this.hash);
$("html, body")
.stop()
.animate(
{
scrollTop: new_target.offset().top - 79
},
500,
"swing",
function() {
window.location.hash = target;
$(document).on("scroll", onScroll);
}
);
});
});
The question doesn't allows us to examine the problem in big detail but here is -at a glance- what is going on:
You are trying to assign an object to a place where only strings are valid.
Take a look at the following example:
function changeText() {
document.getElementById("input").value = "hello"
}
function changeTextWrong() {
document.getElementById("input").value = {link: "hello"}
}
<input id="input" value="sample text"/>
<button onclick="changeText()">change text (OK)</button>
<button onclick="changeTextWrong()">change text (WRONG)</button>
When the input text (equivalent to the url bar) receives the text "hello" it works because "hello" is a text. However when the input text receives an object, this object is then converted into a string. Any object converted into a string is equivalent to "[object Object]".
Solution? Instead of doing window.location.hash = object you very likely need to do something like window.location.hash = object.hash, or window.location.hash = object.WhAtEvEr depending on the object's actual content.
i think you tried to simplify the question without presenting us the complete or relevant code.
From your example, if you only do that it should work but i have a feeling that your code is doing more than that.
#adelriosantiago was right in pointing out that you might return an object instead of the expected string.

How to dynamically append HTML element to component in Vue.js

I'm new to vue.js, before this i'm using jquery or js for my project, i'm working on a project that require me to append HTML element dynamically on button click, and at the same time bind the input value to model, similar to:
$(".button").click(function() {
$("#target").append("<input type='hidden' name='data' v-model='inputModel' value='1'/>");
});
But i need this in Vue.js ways.
Here is my code:
data() {
return {
programmeBanner: [],
dropzoneOptions: {
...
...
init: function () {
this.on("success", function(file, response) {
file.previewElement.id = response;
// this is the part that i want to append the html input into
// the .dz-preview is the target that i want to append
$(".dz-preview[id='"+response+"']").append("<input type='hidden' name='"+fileInputName+"[]' v-model='programmeBanner' class='"+fileInputName+"' value='"+response+"'/>");
});
},
...
Here is a sample that i want to achieve, this is in Jquery, i need it in Vue.js
https://jsfiddle.net/041xnfzu/
Hmm I think you're mixing all kinds of code here :)
First off, you shouldn't use jquery inside VueJS. I think that your setup is a little off. You shouldn't define a whole object with functions and event listeners in your vue data object.
That's what Vue components are for, define methods in your methods property and data in you data property.
Thanks to your jsfiddle example, I have this pure vuejs example for you on codepen: https://codepen.io/bergur/pen/vwRJVx
VueJS code:
new Vue({
el: '#demo',
name: 'Adding html',
data() {
return {
inputs: []
}
},
methods: {
addInput() {
this.inputs.push(this.inputs.length+1)
}
},
computed: {
buttonText() {
return this.showInput ? 'Hide input' : 'Show input'
}
}
})
HTML template
<div id="demo">
<button #click="addInput">Add input</button>
<div v-for="(input, index) in inputs">
<input name="data" v-model="inputs[index]" />
</div>
<p>
First value: {{ inputs[0] }}<br />
Second value: {{ inputs[1] }}
</p>
</div>
Here's a walkthrough of the code.
We create a data property called inputs, that is an array.
We create a method called addInput and all that does is to push a new item into the inputs array
In the template we loop with v-for through our inputs array and render a input for each item in our inputs data property.
We then use v-model to bind each input to its corresponding place in the inputs array.
You can try to change the input value and see that the template updates the value.
So input[0] holds the value for the first input, input[1] holds the value for the second input and so on.
If you want only one element to be appended to component, then you should use v-if
https://v2.vuejs.org/v2/guide/conditional.html#v-if
If you want to append multiple elements, like todo list, you should use v-for
https://v2.vuejs.org/v2/guide/#Conditionals-and-Loops

AnguarJs: ng-repeat only work after clicked button inside directive

I want to bind an array (customLayers) and use it for ng-repeat.
I fill the array inside the kv.colorMap Object.
I have three directives using these technique. But the directive updates the binded array on view ONLY after pressing a functionless button (checkResult), which is inside this directive.
Directive Template Code:
...
<div class="createInfo colorExprContainer">
<div ng-repeat="layer in customLayers">{{layer.color}}</div>
</div>
<div class="buttonWrapper text-center">
<button class="btn" ng-click="checkResult()">Ergebnis prüfen</button>
</div>
...
Directive JavaScript Code:
app.directive('boolKv', function($parse, $timeout){
return {
restrict: 'E',
replace:true,
scope:true,
templateUrl: "directives/boolKV/boolKV.html",
link: function($scope, $element, $attr) {
...
var kv = new BAKV({target: cv[0].id, expr: expr});
$scope.customLayers = kv.colorMap.layers;
...
$scope.checkResult = function(){console.log("it works!");};
});
Does someone have an idea?
Thank you very much!
Thank you MirMasej!
You were right, I was calling it after render. Maybe because I've used the EaselJs Library for canvas. I wanted to get the update after click on a block inside this canvas.
I solved it by adding, if someone has a better idea I would try it:
kv.colorMap.onChangedLayer = function(layer) {
$timeout(function(){
$scope.$apply();
});
};
Im calling this onChangedLayer event after changing the data inside the colorMap object.

How to create a separate scope isolated from ng-repeat in Angular?

I am new to AngularJS and have some trouble understanding the concept of scope in Angular. I have read some posts on stackoverflow as well as online articles, which advise me to create a custom directive to create an isolate scope, but I am getting nowhere...
As for the project I'm working on, I am trying to make a button that when clicked, will trigger a textarea. However, because of ng-repeat, the textarea is triggered for all buttons while I click only one.
My .js file:
angular.module('myApp')
.controller('myCtrl', function ($scope, Question) {
scope.visible = false;
scope.toggle = function() {
scope.visible = !scope.visible;
};
.directive("myDirective", function () {
return {
scope: {
ngClick: '&',
ngShow: '&'
}
}
});
Here is my HTML file:
<ul>
<li ng-repeat="object in objectList">
<button type="text" myDirective ng-click="toggle()">Click</button>
<textarea myDirective ng-show="visible"></textarea>
</li>
</ul>
Angular is creating child (NOT isolated) scope when ng-repeating, try this out, when you ng-init a variable, it is only visible within that repeat div.
<div ng-repeat="i in [0,1,2,3,4,5,6,7,8,9]" ng-init="visible=false">
<button ng-click="visible=!visible">Toggle</button>
<h1 ng-show="visible">look at me!</h1>
</div>
Plunker
There is no need to use a directive. You need to use object in the foreach to refer each item in the loop.
Add visible to each object in objectList:
$scope.objectList = [
{ visible: false },
{ visible: false },
{ visible: false }
];
Then the toggle button will need to pass the object to toggle:
$scope.toggle = function (object) {
object.visible = !object.visible;
};
The ng-show will need to check object.visible and ng-click will need to pass the object:
<button type="text" ng-click="toggle(object)">Click</button>
<textarea ng-show="object.visible"></textarea>
Plunkr

How to open popup windows using angular js after click on div and pass some object to window

I want to know how to open popup window in angularjs with simple animation and background should be blur or dark
and how to pass object to that new popup window
in html
I have this type div
<div class="col-xs-7 col-md-2 rcorners2 " style="height:168px;width:126px; margin-left: 10px" ng-click="clickevent(app)">
app.js I have this:
app.controller('test',['$scope',function($scope){
$scope.clickevent=function(app){
$scope.app=app;
alert(app.name);
}
}]);
this app object content different attributes app name description...
those attribute should display in that new popup window with button
how can I do this?
Wayne suggested ngDialog which is an option but I found it to be really annoying... I simply go with the bootstrap modal or ui.bootstrap $modal... ui.bootstrap just use $modal...
you can use $modal
ref: https://angular-ui.github.io/bootstrap/
app.controller('yourController', yourController);
yourController.$inject = ['$scope', '$modal'];
function yourController($scope, $modal){...}
then start to use it.
use javascript:
assign an object to window
const pageInfo = {
name: 'myPage',
url: 'http://myPage...'
}
window.pageInfo = pageInfo;
window.open(pageInfo.url, "_blank");
then check window.opener on the next page
if (window.opener && window.opener !== null) {
console.log('has initial pageInfo !');
let pageInfo = window.opener.pageInfo;
} else {
console.log('No initial pageInfo !');
}