I'm new to Angular and looking for a way to make a clone button inside a list.
When I click this button, it will clone the object and add a number to the object name:
"new test" - will be changed to "new test (2)" and so on...
It requires to check the last 3 letters every time and check all the objects every time.
Is there any library doing this?
I think you don't need any lib for this. Basically, it you need one loop that looks for duplicates. See an example:
angular.module('myApp', [])
.controller('MyCtrl', function($scope){
$scope.items = ['Sample item'];
$scope.suggestedNewName = 'Sample item';
var isNameOccupied = function(name) {
return $scope.items.indexOf(name) >= 0;
};
$scope.addNewItem = function(){
var suggestedName = $scope.suggestedNewName;
var newName = suggestedName;
for (var i = 2; isNameOccupied(newName); i++) {
newName = suggestedName + " (" + i + ")";
}
$scope.items.push(newName);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<form ng-controller="MyCtrl" ng-submit="addNewItem()">
<ul>
<li ng-repeat="item in items">{{ item }}</li>
</ul>
<label>Suggested name for new item:</label>
<input type="text" ng-model="suggestedNewName">
<button type="submit">Add new item!</button>
</form>
</div>
Related
Hello I'm using CodeIgniter 3 to create a form to submit multiple input type=text and type=file. I currently tackling on the uploading file. My major challenge is to have a upload feature that can upload and delete selected file before submitting. I follow the code from Multiple file upload - with 'remove file' link but the problem is that based on my understanding from what they wrote is that they only delete on the appearance not the selected file itself. I do not plan on using plugin.
View
<div class="files float-left ms-5" id="files1">
<span class="row btn btn-file">
<input type="file" name="files1" multiple />Browse </span>
<ul class="fileList ms-5"></ul>
</div>
Image of the input type=file
External JavaScript
var filesToUpload = [];
$.fn.fileUploader = function (filesToUpload) {
this.closest(".files").change(function (evt) {
for (var i = 0; i < evt.target.files.length; i++) {
filesToUpload.push(evt.target.files[i]);
};
var output = [];
for (var i = 0, f; f = evt.target.files[i]; i++) {
var removeLink = "<a class=\"removeFile\" href=\"#\" data-fileid=\"" + i + "\"><i class='far fa-times-circle fa-lg'></i></a>";
output.push("<li><strong>", escape(f.name), "</strong> - ", removeLink, "</li> ");
}
$(this).children(".fileList").append(output.join(""));
});
};
$(document).on("click",".removeFile", function(e){
e.preventDefault();
var fileName = $(this).parent().children("strong").text();
// loop through the files array and check if the name of that file matches FileName
// and get the index of the match
for(i = 0; i < filesToUpload.length; ++ i){
if(filesToUpload[i].name == fileName){
// remove the one element at the index where we get a match
filesToUpload.splice(i, 1);
}
}
// remove the <li> element of the removed file from the page DOM
$(this).parent().remove();
});
$("#files1").fileUploader(filesToUpload);
I need help of professionals at Apps script. I have the project implemented by web-app.
I wrote script on server-part
var url = "https://docs.google.com/spreadsheets/d/1s8l-8N8dI-GGJi_mmYs2f_88VBcnzWfv3YHgk1HvIh0/edit?usp=sharing";
var sprSRCH = SpreadsheetApp.openByUrl(url);
let sheetSRCHSSCC = sprSRCH.getSheetByName("PUTAWAY_TO");
function GetQ(){
var QPLAN = sheetSRCHSSCC.getRange("M2:M").getValues().filter(String).length;
var myArray = sheetSRCHSSCC.getRange("O2:O" + (QPLAN + 1)).getValues();
var QFACT = 0;
for (i = 0; i < myArray.length; i++) {
if (myArray[i] != "") {
QFACT += 1
}
}
}
I need to return values from this function to inputs:
QFACT to FACT
QPLAN to PLAN
<div class="input-field col s3">
<input disabled value="" id="PLAN" type="text" >
<label for="disabled">PLAN</label>
</div>
<div class="input-field col s3">
<input disabled value="" id="FACT" type="text" >
<label for="disabled">FACT</label>
</div>
I will be grateful for the help. I'm new at this))
If you are using Apps Script deploying Web App, I can see 2 possibilities :
1/ Get data at the loading of the page (and only at the loading) :
In code.gs :
function doGet() {
var tmp = HtmlService.createTemplateFromFile('page');
tmp.QFACT = "hello";
tmp.PLAN = "World!";
return tmp.evaluate();
}
In page.html :
<html>
<body>
<h5><?= QFACT ?></h5>
<h5><?= QPLAN ?></h5>
</body>
</html>
2/ If you need to refresh the data by click button, or something else, you will need to operate diffently :
Add a page-js.html to your project, and bind it at the end of your page.html
<html>
<body>
<h5 id="QFACT"></h5>
<h5 id="QPLAN"></h5>
</body>
<?!= include("page-js"); ?>
</html>
then in your page-js.html :
<script>
function refresh() {
google.script.run.withSuccessHandler(callback).refresh();
}
function callback(e) {
document.getElementById('QPLAN').innerHTML = e.QPLAN;
document.getElementById('QFACT').innerHTML = e.QFACT;
}
</script>
and finally add the refresh() function in your code.gs :
function refresh() {
var obj = {};
obj.QPLAN = "QPLAN";
obj.QFACT = "QFACT";
return obj;
}
I'd like to use Knockout data binding to update weather API data in my html div element. Currently, I am using jQuery to update the DOM but I prefer to use Knockout. I also want to dynamically change the location zip so weather is specific to that one location in my div. I have an array for locations.
Here's my code:
html:
var zip = locations[0].zipcode;
var myOpenWeatherAPIKey = 'xxxxxxxxxxxxxxxxxxxx';
var openWeatherMapUrl = "http://api.openweathermap.org/data/2.5/weather?zip=" + zip + ",us&APPID=" + myOpenWeatherAPIKey + "&units=imperial";
console.log(zip);
//using JSON method for retrieving API data
$.getJSON(openWeatherMapUrl, function(data) {
var parameters = $(".weather-data ul");
var iconCode = data.weather[0].icon;
var iconDescription = data.weather[0].main;
var iconUrl = "http://openweathermap.org/img/w/" + iconCode + ".png";
detail = data.main;
windspd = data.wind;
parameters.append('<li>Temp: ' + Math.round(detail.temp) + '° F <br></li>');
parameters.append('<li><img style="width: 25px" src="' + iconUrl + '"> ' + iconDescription + '</li>');
}).fail(weatherError = function(e) {
$(".weather-data").append("OpenWeatherAPI is unable to load!");
});
<div id="open-weather" class="open-weather">
<div id="weather-data" class="weather-data">
<p> <br> Current Weather</p>
<ul id="weather-items" class="weather-items">
</ul>
</div>
</div>
Thanks,
You can write a custom KO binding or a custom KO component to encapsulate your markup, API keys, jQuery, and XHR calls.
With your code and use case, a component sounds like a good fit. Then your consuming markup could look like
<weather params="zip: myZipCode"></weather>
where myZipCode is a ko.observable in your consuming page's view model.
Update 1
Added roughed in code for encapsulating inside a KO component.
Update 2
Moved jquery DOM references out of KO component code so component template uses KO bindings. Added consuming page view model to show full example.
function openWeatherComponentViewModel(params) {
var self = this;
self.zip = ko.observable(ko.unwrap(params.zip));
self.temperature = ko.observable();
self.iconCode = ko.observable();
self.iconUrl = ko.pureComputed(function() {
return "http://openweathermap.org/img/w/" + self.iconCode() + ".png";
});
self.iconDescription = ko.observable();
self.hasWeather = ko.observable(false);
self.errorMessage = ko.observable();
var apiKey = 'xxxxxxxxxxxxxxxxxxxx';
var url = "https://api.openweathermap.org/data/2.5/weather?zip=" + self.zip() + ",us&APPID=" + apiKey + "&units=imperial";
$.getJSON(url, function(data) {
self.temperature(Math.round(data.main.temp));
self.iconCode(data.weather[0].icon);
self.iconDescription(data.weather[0].main);
self.hasWeather(true);
}).fail(function(error) {
self.hasWeather(false);
self.errorMessage("OpenWeatherAPI is unable to load! " + error.responseJSON.message);
});
}
ko.components.register('weather-component', {
viewModel: openWeatherComponentViewModel,
template: `<div id="open-weather" class="open-weather">
<div id="weather-data" class="weather-data" data-bind="if: hasWeather()">
<p>Current Weather for Zip Code <span data-bind="text: zip"></span></p>
<ul id="weather-items" class="weather-items">
<li>Temp: <span data-bind="text: temperature"></span>° F</li>
<li><img style="width: 25px" data-bind="attr: { src: iconUrl }"><span data-bind="text: iconDescription"></span></img></li>
</ul>
</div>
<div id="weather-data" class="weather-data" data-bind="if: !hasWeather()">
<span data-bind="text: errorMessage"></span>
<div>
</div>`
});
function myConsumingPageViewModel() {
var self = this;
self.myZipCode = ko.observable("80130");
}
var vm = new myConsumingPageViewModel();
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<weather-component params="zip: myZipCode"></weather-component>
I want to print alphabets for marking options of questions using ng-repeat directive in Angular.
<div ng-repeat="options in $root.options">
//print alphabets in sequence here//:{{options}}
</div>
$root.options have 4 option, now i want it to be printed like
A: option 1
B: option 2
C: option 3
D: option 4
PS: I am not using HTML list neither I am planning to.
One solution would be to create a string in your $scope as follows:
$scope.alphabet = 'abcdefghijklmnopqrstuvwxyz';
You can then use track by $index in your ng-repeat to access letters from the string as follows:
<div ng-repeat="options in $root.options track by $index">
{{ alphabet[$index] }}: {{ options }}
</div>
Here you go:
First define all the alphabets:
$scope.letterArray = [];
for(var i = 0; i < 26; i++) {
$scope.letterArray.push(String.fromCharCode(65 + i));
}
And then use it:
<div ng-repeat="options in $root.options">
{{letterArray[$index]}}: option {{$option}}
</div>
See it working below:
var myApp = angular.module("sa", []);
myApp.controller("foo", function($scope) {
$scope.letterArray = [];
for (var i = 0; i < 26; i++) {
$scope.letterArray.push(String.fromCharCode(65 + i));
}
$scope.options = [{
name: "hello foo"
}, {
name: "hello bar"
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sa" ng-controller="foo">
<div ng-repeat="option in options">
{{letterArray[$index]}}: {{option.name}} {{$index}}
</div>
</div>
1. level1
-lvl1A
--lvl1A1
--lvl1A2
---lvl1A2X
---lvl1A2Y
-lvl2A
--lvl2A1
--lvl2A2
2. level2
this is just the sample of multilevel ng-repeat ul li element.
on click of any level only next level data will show or hide not the entire data.
kindly give me some solution to this scenario.
Thanks in Advance.
I have done this in some of my spare time.. it might not be the best way to do it.
angular.module("myApp", []).
controller("TreeController", ['$scope',
function($scope) {
$scope.delete = function(data) {
data.nodes = [];
return false;
};
$scope.add = function(data) {
var post = data.nodes.length + 1;
var newName = data.name + '-' + post;
var showSub = false;
data.nodes.push({
name: newName,
showSub: showSub,
nodes: []
});
return false;
};
$scope.tree = [{
name: "Node",
showSub: false,
nodes: []
}];
}
]);
<script type="text/ng-template" id="tree_item_renderer.html">
{{data.name}}
<button ng-click="add(data); $event.stopPropagation();">Add node</button>
<button ng-click="delete(data); $event.stopPropagation();" ng-show="data.nodes.length > 0">Delete nodes</button>
<ul ng-show="data.showSub">
<li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'" ng-click="data.showSub = !data.showSub; $event.stopPropagation();"></li>
</ul>
</script>
<ul ng-app="Application" ng-controller="TreeController">
<li ng-repeat="data in tree" ng-include="'tree_item_renderer.html'" ng-click="data.showSub = !data.showSub"></li>
</ul>
jsFiddle