আমি অ্যাজাক্স ব্যবহার করে একটি জ্যাঙ্গো ফর্মসেটে স্বয়ংক্রিয়ভাবে নতুন ফর্মগুলি যুক্ত করতে চাই, যাতে ব্যবহারকারী কোনও "অ্যাড" বোতামটি ক্লিক করেন তখন এটি জাভাস্ক্রিপ্ট চালায় যা পৃষ্ঠায় একটি নতুন ফর্ম (যা ফর্মসেটের অংশ) যুক্ত করে।
আমি অ্যাজাক্স ব্যবহার করে একটি জ্যাঙ্গো ফর্মসেটে স্বয়ংক্রিয়ভাবে নতুন ফর্মগুলি যুক্ত করতে চাই, যাতে ব্যবহারকারী কোনও "অ্যাড" বোতামটি ক্লিক করেন তখন এটি জাভাস্ক্রিপ্ট চালায় যা পৃষ্ঠায় একটি নতুন ফর্ম (যা ফর্মসেটের অংশ) যুক্ত করে।
উত্তর:
JQuery ব্যবহার করে আমি এটি এটি করি :
আমার টেম্পলেট:
<h3>My Services</h3>
{{ serviceFormset.management_form }}
{% for form in serviceFormset.forms %}
<div class='table'>
<table class='no_error'>
{{ form.as_table }}
</table>
</div>
{% endfor %}
<input type="button" value="Add More" id="add_more">
<script>
$('#add_more').click(function() {
cloneMore('div.table:last', 'service');
});
</script>
একটি জাভাস্ক্রিপ্ট ফাইলে:
function cloneMore(selector, type) {
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
এর মানে কি:
cloneMore
গ্রহণ selector
প্রথম আর্গুমেন্ট, এবং type
2nd এক হিসাবে formset করুন। যা করা selector
উচিত তা হ'ল এটির নকল করা উচিত। এই ক্ষেত্রে, আমি এটি পাস করেছি div.table:last
যাতে jQuery ক্লাসের সাথে শেষ সারণির সন্ধান করে table
। এর :last
অংশটি গুরুত্বপূর্ণ কারণ selector
এটি নতুন ফর্মটি কী পরে প্রবেশ করানো হবে তা নির্ধারণ করতেও ব্যবহৃত হয়। আপনি সম্ভবত অন্যান্য ফর্মগুলির শেষে এটি চাইবেন। type
যুক্তি, যাতে আমরা আপডেট করতে পারেন হয় management_form
ক্ষেত্র, উল্লেখযোগ্য হল TOTAL_FORMS
, সেইসাথে প্রকৃত ফর্ম ক্ষেত্রগুলি। আপনার কাছে যদি বলুন, Client
মডেলগুলি দিয়ে পূর্ণরূপযুক্ত একটি ফর্মসেট থাকে তবে পরিচালন ক্ষেত্রগুলির আইডি থাকবে id_clients-TOTAL_FORMS
এবং id_clients-INITIAL_FORMS
যখন ফর্ম ক্ষেত্রগুলির id_clients-N-fieldname
সাথে ফর্ম্যাট থাকবেN
ফর্ম নম্বর হচ্ছে, দিয়ে শুরু 0
। সুতরাং type
যুক্তির সাহায্যে cloneMore
ফাংশনটি বর্তমানে কতগুলি ফর্ম রয়েছে তা দেখায় এবং নতুন ফর্মের ভিতরে প্রতিটি ইনপুট এবং লেবেল দিয়ে যায় এবং সমস্ত ক্ষেত্রের নাম / আইডিগুলিকে কিছু পছন্দ id_clients-(N)-name
করে এমনগুলি প্রতিস্থাপন id_clients-(N+1)-name
করে। এটি সমাপ্ত হওয়ার পরে, এটি TOTAL_FORMS
নতুন ফর্মটি প্রতিবিম্বিত করতে ক্ষেত্রটি আপডেট করে এবং সেটটির শেষে এটি যুক্ত করে।
এই ফাংশনটি আমার জন্য বিশেষভাবে সহায়ক কারণ যখন আমি কোনও ফর্মসেটে আরও ফর্ম সরবরাহ করতে চাই তখন এটি অ্যাপটি জুড়ে আমাকে এটি ব্যবহার করার অনুমতি দেয় এবং নকল করার জন্য আমার কোনও গোপন "টেম্পলেট" ফর্ম থাকা দরকার না যতক্ষণ না আমি এটি ফর্মসেটের নাম এবং ফর্ম্যাটটি ফর্মটি আউট করা হয় সেই বিন্যাসটি পাস করি। আশা করি এটা সাহায্য করবে.
prefix
জাজানো ১.১ এ আপনাকে ফর্মসেট অবজেক্টের সদস্যকে একটি মূল্য নির্ধারণ করতে হবে । এটি ফাংশনের type
আর্গুমেন্টের সমান মান হওয়া উচিত cloneMore
।
empty_form
টেম্পলেট হিসাবে ব্যবহার করে পাওলো এর উত্তরের সরলিকৃত সংস্করণ ।
<h3>My Services</h3>
{{ serviceFormset.management_form }}
<div id="form_set">
{% for form in serviceFormset.forms %}
<table class='no_error'>
{{ form.as_table }}
</table>
{% endfor %}
</div>
<input type="button" value="Add More" id="add_more">
<div id="empty_form" style="display:none">
<table class='no_error'>
{{ serviceFormset.empty_form.as_table }}
</table>
</div>
<script>
$('#add_more').click(function() {
var form_idx = $('#id_form-TOTAL_FORMS').val();
$('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
$('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
});
</script>
CompetitorFormSet = modelformset_factory(ProjectCompetitor, formset=CompetitorFormSets)
ctx['competitor_form_set'] = CompetitorFormSet(request.POST)
করি তখন পরিষ্কার পদ্ধতিতে আমি কেবল একটি ফর্ম পাই। কীভাবে দয়া করে দৃষ্টিতে এটি মোকাবেলা করবেন তা ব্যাখ্যা করতে পারেন
empty_form
) এর দুর্দান্ত ব্যবহার করে যা আমি প্রশংসা করি।
আমি কিছুক্ষণ আগে কাজ করেছি এমন একটি অ্যাপ্লিকেশন থেকে একটি স্নিপেট পোস্ট করেছি । পাওলো এর মতো, তবে আপনাকে ফর্মগুলি মুছতে দেয়।
পাওলোর পরামর্শটি একটি সতর্কতামূলক - ব্রাউজারের পিছনে / ফরোয়ার্ড বোতামগুলির সাথে সুন্দরভাবে কাজ করে।
পাওলো স্ক্রিপ্টের সাহায্যে তৈরি গতিশীল উপাদানগুলি যদি ব্যবহারকারী ফিরে / ফরোয়ার্ড বোতামটি ব্যবহার করে ফর্মसेटটিতে ফিরে আসে তবে তা রেন্ডার হবে না। এমন একটি সমস্যা যা কারও কারও জন্য চুক্তিভঙ্গকারী হতে পারে।
উদাহরণ:
1) ব্যবহারকারী "অ্যাড-মোর" বোতামটি ব্যবহার করে ফর্মসেটে দুটি নতুন ফর্ম যুক্ত করেন
2) ব্যবহারকারী ফর্মগুলি পপুলেট করে এবং ফর্মসেট জমা দেয়
3) ব্যবহারকারী ব্রাউজারে পিছনের বোতামটি ক্লিক করে
৪) ফর্মसेटটি এখন মূল ফর্মটিতে হ্রাস পেয়েছে, সমস্ত গতিশীল যুক্ত ফর্মগুলি নেই
এটি পাওলো লিপির কোনও ক্ষেত্রেই ত্রুটি নয়; তবে ডোম হেরফের এবং ব্রাউজারের ক্যাশে দিয়ে জীবনের একটি বাস্তবতা।
আমি মনে করি সেশনে ফর্মের মানগুলি সঞ্চয় করতে পারে এবং ফর্মसेटটি আবার উপাদান তৈরি করতে লোড করে এবং সেশন থেকে মানগুলি পুনরায় লোড করতে পারে; তবে একই ব্যবহারকারী এবং ফর্মের একাধিক উদাহরণ সম্পর্কে আপনি যে কী পোষক হতে চান তার উপর নির্ভর করে এটি খুব জটিল হয়ে উঠতে পারে।
এটি মোকাবেলার জন্য কারও কাছে ভাল পরামর্শ আছে?
ধন্যবাদ!
গতিশীল জ্যাঙ্গো ফর্মগুলির নিম্নলিখিত সমাধানগুলি দেখুন:
http://code.google.com/p/django-dynamic-formset/
https://github.com/javisantana/django-dinamyc-form/tree/master/frm
তারা উভয়ই jQuery ব্যবহার করে এবং জ্যাঙ্গো-নির্দিষ্ট। প্রথমটিকে কিছুটা বেশি পালিশ করা মনে হয় এবং এমন একটি ডাউনলোড অফার করে যা ডাব্লু / ডেমো আসে যা দুর্দান্ত।
অনুকরণ করুন এবং অনুকরণ করুন:
<input>
ক্ষেত্রের একটি নোট নিন ।<input>
ক্ষেত্রগুলি কীভাবে পরিবর্তিত হয়েছে তার একটি নোট নিন ।যদিও আমি জানি যে ফর্মসেটগুলি বিশেষ লুকানো <input>
ক্ষেত্রগুলি ব্যবহার করে এবং প্রায় স্ক্রিপ্টটি কী করতে হবে তা আমি জানি তবে আমি আমার মাথার উপরের অংশের বিবরণগুলি স্মরণ করতে পারি না। আমি উপরে যা বর্ণনা করেছি তা হল আপনার পরিস্থিতিতে আমি কী করব।
এটির জন্য একটি জকিরি প্লাগইন রয়েছে , আমি এটি জাজানো ১.৩ এ ইনলাইন_ফর্ম সেট সহ ব্যবহার করেছি এবং এটি প্রিপোপুলেশন, ক্লায়েন্ট সাইড ফর্ম যুক্ত করা, অপসারণ এবং একাধিক ইনলাইন_ফর্মসেট সহ পুরোপুরি কাজ করে।
একটি বিকল্প হ'ল প্রতিটি সম্ভাব্য ফর্মের সাথে একটি ফর্মसेट তৈরি করা, তবে প্রাথমিকভাবে অপ্রয়োজনীয় ফর্মগুলি গোপনে সেট করা - অর্থাৎ display: none;
,। যখন কোনও ফর্ম প্রদর্শন করা প্রয়োজন, এটিতে সিএসএস প্রদর্শন সেট করুনblock
বা উপযুক্ত
আপনার "আজাক্স" কী করছে তার আরও বিশদ না জেনে আরও বিশদ প্রতিক্রিয়া জানানো কঠিন।
আরেকটি ক্লোনমোর সংস্করণ, যা ক্ষেত্রগুলি নির্বাচনী স্যানিটাইজেশনের অনুমতি দেয়। যখন আপনাকে বেশ কয়েকটি ক্ষেত্র মুছে ফেলা থেকে রোধ করতে হবে তখন এটি ব্যবহার করুন।
$('table tr.add-row a').click(function() {
toSanitize = new Array('id', 'product', 'price', 'type', 'valid_from', 'valid_until');
cloneMore('div.formtable table tr.form-row:last', 'form', toSanitize);
});
function cloneMore(selector, type, sanitize) {
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var namePure = $(this).attr('name').replace(type + '-' + (total-1) + '-', '');
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).removeAttr('checked');
if ($.inArray(namePure, sanitize) != -1) {
$(this).val('');
}
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
ক্লোনমোর ফাংশন নিয়ে একটি ছোট সমস্যা রয়েছে। যেহেতু এটি জ্যাঙ্গো স্বয়ংক্রিয়ভাবে উত্পন্ন উত্পাদিত লুকানো ক্ষেত্রগুলির মানও পরিষ্কার করছে, তাই আপনি যদি একাধিক খালি ফর্মের সাথে একটি ফর্মसेट সংরক্ষণ করার চেষ্টা করেন তবে এটি জাঙ্গোর অভিযোগ করতে পারে।
এখানে একটি সংশোধন করা হয়েছে:
function cloneMore(selector, type) {
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
if ($(this).attr('type') != 'hidden') {
$(this).val('');
}
$(this).attr({'name': name, 'id': id}).removeAttr('checked');
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
আমি মনে করি এটি একটি আরও ভাল সমাধান।
জ্যাঙ্গোতে আপনি কীভাবে একটি গতিশীল ফর্মसेट তৈরি করবেন?
জিনিসগুলি ক্লোন করে না:
ওখানকার কোডারদের জন্য যারা উপরের সমাধানগুলি আরও ভালভাবে বোঝার জন্য শিকারের সংস্থানগুলি করছেন:
উপরের লিঙ্কটি পড়ার পরে, জাঙ্গো ডকুমেন্টেশন এবং পূর্ববর্তী সমাধানগুলি আরও অনেক বেশি অর্থবোধ করা উচিত।
আমি যা বিভ্রান্ত হচ্ছিলাম তার দ্রুত সংক্ষিপ্তসার হিসাবে: ম্যানেজমেন্ট ফর্মের মধ্যে ফর্মগুলির একটি ওভারভিউ রয়েছে। জ্যাঙ্গোকে আপনি যে ফর্মগুলি যুক্ত করেন সে সম্পর্কে সচেতন হওয়ার জন্য আপনার অবশ্যই সেই তথ্যটি সঠিক রাখতে হবে। (সম্প্রদায়, আমার কিছু শব্দবন্ধ এখানে বন্ধ থাকলে দয়া করে আমাকে পরামর্শ দিন D আমি জাজানোতে নতুন)
@ পাওলো বার্গান্টিনো
সংযুক্ত সমস্ত হ্যান্ডলারের ক্লোন করতে কেবল লাইনটি সংশোধন করুন
var newElement = $(selector).clone();
জন্য
var newElement = $(selector).clone(true);
হ্যাঁ, আপনার যদি সীমাবদ্ধ সংখ্যার এন্ট্রি থাকে তবে আমি এইচটিএমএল এ কেবল তাদের রেন্ডারিংয়ের পরামর্শ দেব। (আপনি যদি না করেন তবে আপনাকে অন্য একটি পদ্ধতি ব্যবহার করতে হবে)।
আপনি এগুলি এগুলিকে লুকিয়ে রাখতে পারেন:
{% for form in spokenLanguageFormset %}
<fieldset class="languages-{{forloop.counter0 }} {% if spokenLanguageFormset.initial_forms|length < forloop.counter and forloop.counter != 1 %}hidden-form{% endif %}">
তাহলে জেএস সত্যিই সহজ:
addItem: function(e){
e.preventDefault();
var maxForms = parseInt($(this).closest("fieldset").find("[name*='MAX_NUM_FORMS']").val(), 10);
var initialForms = parseInt($(this).closest("fieldset").find("[name*='INITIAL_FORMS']").val(), 10);
// check if we can add
if (initialForms < maxForms) {
$(this).closest("fieldset").find("fieldset:hidden").first().show();
if ($(this).closest("fieldset").find("fieldset:visible").length == maxForms ){
// here I'm just hiding my 'add' link
$(this).closest(".control-group").hide();
};
};
}
কারণ উপরের সমস্ত উত্তর jQuery ব্যবহার করে এবং কিছু জিনিস কিছু জটিল করে তোলে আমি নিম্নলিখিত স্ক্রিপ্টটি লিখেছিলাম:
function $(selector, element) {
if (!element) {
element = document
}
return element.querySelector(selector)
}
function $$(selector, element) {
if (!element) {
element = document
}
return element.querySelectorAll(selector)
}
function hasReachedMaxNum(type, form) {
var total = parseInt(form.elements[type + "-TOTAL_FORMS"].value);
var max = parseInt(form.elements[type + "-MAX_NUM_FORMS"].value);
return total >= max
}
function cloneMore(element, type, form) {
var totalElement = form.elements[type + "-TOTAL_FORMS"];
total = parseInt(totalElement.value);
newElement = element.cloneNode(true);
for (var input of $$("input", newElement)) {
input.name = input.name.replace("-" + (total - 1) + "-", "-" + total + "-");
input.value = null
}
total++;
element.parentNode.insertBefore(newElement, element.nextSibling);
totalElement.value = total;
return newElement
}
var addChoiceButton = $("#add-choice");
addChoiceButton.onclick = function() {
var choices = $("#choices");
var createForm = $("#create");
cloneMore(choices.lastElementChild, "choice_set", createForm);
if (hasReachedMaxNum("choice_set", createForm)) {
this.disabled = true
}
};
প্রথমে আপনার অটো_আইডিটিকে মিথ্যা হিসাবে সেট করা উচিত এবং তাই আইডি এবং নামের সদৃশটি অক্ষম করা উচিত । যেহেতু ইনপুট নামগুলি সেখানে ফর্মটিতে অনন্য হতে হবে, সমস্ত পরিচয় তাদের সাথে করা হয়, আইডির সাথে নয়। এছাড়াও আপনি প্রতিস্থাপন আছে form
, type
এবং formset কন্টেনার। (উপরের উদাহরণে choices
)